From: Scott Cantor Date: Fri, 13 Oct 2006 18:40:48 +0000 (+0000) Subject: gcc const fix, converted linefeeds X-Git-Tag: 1.0-alpha1~164 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-xmltooling.git;a=commitdiff_plain;h=e7a65d784215bc04355f014141219b3e7ab4559a gcc const fix, converted linefeeds --- diff --git a/xmltooling/AbstractAttributeExtensibleXMLObject.cpp b/xmltooling/AbstractAttributeExtensibleXMLObject.cpp index 3ebf6c5..a445248 100644 --- a/xmltooling/AbstractAttributeExtensibleXMLObject.cpp +++ b/xmltooling/AbstractAttributeExtensibleXMLObject.cpp @@ -1,101 +1,101 @@ -/* - * 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. - */ - -/** - * AbstractAttributeExtensibleXMLObject.cpp - * - * Extension of AbstractDOMCachingXMLObject that implements an AttributeExtensibleXMLObject. - */ - -#include "internal.h" -#include "AbstractAttributeExtensibleXMLObject.h" - -#include -#include - -using namespace xmltooling; -using namespace std; - -set AttributeExtensibleXMLObject::m_idAttributeSet; - -AbstractAttributeExtensibleXMLObject::~AbstractAttributeExtensibleXMLObject() -{ - for (map::iterator i=m_attributeMap.begin(); i!=m_attributeMap.end(); i++) - XMLString::release(&(i->second)); -} - -AbstractAttributeExtensibleXMLObject::AbstractAttributeExtensibleXMLObject(const AbstractAttributeExtensibleXMLObject& src) - : AbstractXMLObject(src) -{ - m_idAttribute = m_attributeMap.end(); - for (map::const_iterator i=src.m_attributeMap.begin(); i!=src.m_attributeMap.end(); i++) { - m_attributeMap[i->first] = XMLString::replicate(i->second); - } - if (src.m_idAttribute != src.m_attributeMap.end()) { - m_idAttribute = m_attributeMap.find(src.m_idAttribute->first); - } -} - -void AbstractAttributeExtensibleXMLObject::setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID) -{ - map::iterator i=m_attributeMap.find(qualifiedName); - if (i!=m_attributeMap.end()) { - releaseThisandParentDOM(); - XMLString::release(&(i->second)); - if (value) { - i->second=XMLString::replicate(value); - } - else { - if (m_idAttribute==i) - m_idAttribute=m_attributeMap.end(); - m_attributeMap.erase(i); - } - - if (ID) { - m_idAttribute=i; - } - } - else if (value) { - releaseThisandParentDOM(); - m_attributeMap[qualifiedName]=XMLString::replicate(value); - if (ID) { - m_idAttribute = m_attributeMap.find(qualifiedName); - } - } -} - -void AbstractAttributeExtensibleXMLObject::unmarshallExtensionAttribute(const DOMAttr* attribute) -{ - QName q(attribute->getNamespaceURI(),attribute->getLocalName(),attribute->getPrefix()); - bool ID = isRegisteredIDAttribute(q); - setAttribute(q,attribute->getNodeValue(),ID); - if (ID) { - attribute->getOwnerElement()->setIdAttributeNode(attribute); - } -} - -void AbstractAttributeExtensibleXMLObject::marshallExtensionAttributes(DOMElement* domElement) const -{ - for (map::const_iterator i=m_attributeMap.begin(); i!=m_attributeMap.end(); i++) { - DOMAttr* attr=domElement->getOwnerDocument()->createAttributeNS(i->first.getNamespaceURI(),i->first.getLocalPart()); - if (i->first.hasPrefix()) - attr->setPrefix(i->first.getPrefix()); - attr->setNodeValue(i->second); - domElement->setAttributeNode(attr); - if (m_idAttribute==i) - domElement->setIdAttributeNode(attr); - } -} +/* + * 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. + */ + +/** + * AbstractAttributeExtensibleXMLObject.cpp + * + * Extension of AbstractDOMCachingXMLObject that implements an AttributeExtensibleXMLObject. + */ + +#include "internal.h" +#include "AbstractAttributeExtensibleXMLObject.h" + +#include +#include + +using namespace xmltooling; +using namespace std; + +set AttributeExtensibleXMLObject::m_idAttributeSet; + +AbstractAttributeExtensibleXMLObject::~AbstractAttributeExtensibleXMLObject() +{ + for (map::iterator i=m_attributeMap.begin(); i!=m_attributeMap.end(); i++) + XMLString::release(&(i->second)); +} + +AbstractAttributeExtensibleXMLObject::AbstractAttributeExtensibleXMLObject(const AbstractAttributeExtensibleXMLObject& src) + : AbstractXMLObject(src) +{ + m_idAttribute = m_attributeMap.end(); + for (map::const_iterator i=src.m_attributeMap.begin(); i!=src.m_attributeMap.end(); i++) { + m_attributeMap[i->first] = XMLString::replicate(i->second); + } + if (src.m_idAttribute != src.m_attributeMap.end()) { + m_idAttribute = m_attributeMap.find(src.m_idAttribute->first); + } +} + +void AbstractAttributeExtensibleXMLObject::setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID) +{ + map::iterator i=m_attributeMap.find(qualifiedName); + if (i!=m_attributeMap.end()) { + releaseThisandParentDOM(); + XMLString::release(&(i->second)); + if (value) { + i->second=XMLString::replicate(value); + } + else { + if (m_idAttribute==i) + m_idAttribute=m_attributeMap.end(); + m_attributeMap.erase(i); + } + + if (ID) { + m_idAttribute=i; + } + } + else if (value) { + releaseThisandParentDOM(); + m_attributeMap[qualifiedName]=XMLString::replicate(value); + if (ID) { + m_idAttribute = m_attributeMap.find(qualifiedName); + } + } +} + +void AbstractAttributeExtensibleXMLObject::unmarshallExtensionAttribute(const DOMAttr* attribute) +{ + QName q(attribute->getNamespaceURI(),attribute->getLocalName(),attribute->getPrefix()); + bool ID = isRegisteredIDAttribute(q); + setAttribute(q,attribute->getNodeValue(),ID); + if (ID) { + attribute->getOwnerElement()->setIdAttributeNode(attribute); + } +} + +void AbstractAttributeExtensibleXMLObject::marshallExtensionAttributes(DOMElement* domElement) const +{ + for (map::const_iterator i=m_attributeMap.begin(); i!=m_attributeMap.end(); i++) { + DOMAttr* attr=domElement->getOwnerDocument()->createAttributeNS(i->first.getNamespaceURI(),i->first.getLocalPart()); + if (i->first.hasPrefix()) + attr->setPrefix(i->first.getPrefix()); + attr->setNodeValue(i->second); + domElement->setAttributeNode(attr); + if (m_idAttribute==i) + domElement->setIdAttributeNode(attr); + } +} diff --git a/xmltooling/AbstractAttributeExtensibleXMLObject.h b/xmltooling/AbstractAttributeExtensibleXMLObject.h index 9480cff..3f50678 100644 --- a/xmltooling/AbstractAttributeExtensibleXMLObject.h +++ b/xmltooling/AbstractAttributeExtensibleXMLObject.h @@ -1,98 +1,98 @@ -/* - * 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 AbstractAttributeExtensibleXMLObject.h - * - * AbstractXMLObject mixin that implements AttributeExtensibleXMLObject - */ - -#ifndef __xmltooling_absattrextxmlobj_h__ -#define __xmltooling_absattrextxmlobj_h__ - -#include -#include -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * AbstractXMLObject mixin that implements AttributeExtensibleXMLObject. - * Inherit from this class to add support for attribute wildcarding. - */ - class XMLTOOL_API AbstractAttributeExtensibleXMLObject - : public virtual AttributeExtensibleXMLObject, public virtual AbstractXMLObject - { - public: - virtual ~AbstractAttributeExtensibleXMLObject(); - - const XMLCh* getAttribute(const QName& qualifiedName) const { - std::map::const_iterator i=m_attributeMap.find(qualifiedName); - return (i==m_attributeMap.end()) ? NULL : i->second; - } - - void setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID=false); - - const std::map& getExtensionAttributes() const { - return m_attributeMap; - } - - const XMLCh* getXMLID() const { - return (m_idAttribute == m_attributeMap.end()) ? NULL : m_idAttribute->second; - } - - protected: - AbstractAttributeExtensibleXMLObject() { - m_idAttribute = m_attributeMap.end(); - } - - /** Copy constructor. */ - AbstractAttributeExtensibleXMLObject(const AbstractAttributeExtensibleXMLObject& src); - - /** - * Assists in the unmarshalling of extension attributes. - * - * @param attribute the DOM attribute node being unmarshalled - */ - void unmarshallExtensionAttribute(const DOMAttr* attribute); - - /** - * Assists in the marshalling of extension attributes. - * - * @param domElement the DOM element against which to marshall the attributes - */ - void marshallExtensionAttributes(DOMElement* domElement) const; - - private: - /** Map of arbitrary attributes. */ - std::map m_attributeMap; - - /** Points to the last attribute designated as an XML ID. */ - std::map::const_iterator m_idAttribute; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_absattrextxmlobj_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 AbstractAttributeExtensibleXMLObject.h + * + * AbstractXMLObject mixin that implements AttributeExtensibleXMLObject + */ + +#ifndef __xmltooling_absattrextxmlobj_h__ +#define __xmltooling_absattrextxmlobj_h__ + +#include +#include +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * AbstractXMLObject mixin that implements AttributeExtensibleXMLObject. + * Inherit from this class to add support for attribute wildcarding. + */ + class XMLTOOL_API AbstractAttributeExtensibleXMLObject + : public virtual AttributeExtensibleXMLObject, public virtual AbstractXMLObject + { + public: + virtual ~AbstractAttributeExtensibleXMLObject(); + + const XMLCh* getAttribute(const QName& qualifiedName) const { + std::map::const_iterator i=m_attributeMap.find(qualifiedName); + return (i==m_attributeMap.end()) ? NULL : i->second; + } + + void setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID=false); + + const std::map& getExtensionAttributes() const { + return m_attributeMap; + } + + const XMLCh* getXMLID() const { + return (m_idAttribute == m_attributeMap.end()) ? NULL : m_idAttribute->second; + } + + protected: + AbstractAttributeExtensibleXMLObject() { + m_idAttribute = m_attributeMap.end(); + } + + /** Copy constructor. */ + AbstractAttributeExtensibleXMLObject(const AbstractAttributeExtensibleXMLObject& src); + + /** + * Assists in the unmarshalling of extension attributes. + * + * @param attribute the DOM attribute node being unmarshalled + */ + void unmarshallExtensionAttribute(const DOMAttr* attribute); + + /** + * Assists in the marshalling of extension attributes. + * + * @param domElement the DOM element against which to marshall the attributes + */ + void marshallExtensionAttributes(DOMElement* domElement) const; + + private: + /** Map of arbitrary attributes. */ + std::map m_attributeMap; + + /** Points to the last attribute designated as an XML ID. */ + std::map::const_iterator m_idAttribute; + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_absattrextxmlobj_h__ */ diff --git a/xmltooling/AbstractComplexElement.h b/xmltooling/AbstractComplexElement.h index ba8b862..636b042 100644 --- a/xmltooling/AbstractComplexElement.h +++ b/xmltooling/AbstractComplexElement.h @@ -1,85 +1,85 @@ -/* - * 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 xmltooling/AbstractComplexElement.h - * - * AbstractXMLObject mixin that implements children - */ - -#ifndef __xmltooling_abscomplexel_h__ -#define __xmltooling_abscomplexel_h__ - -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * AbstractXMLObject mixin that implements children. - * Inherit from this class to implement an element with child objects and mixed content. - */ - class XMLTOOL_API AbstractComplexElement : public virtual AbstractXMLObject - { - public: - virtual ~AbstractComplexElement(); - - bool hasChildren() const { - return !m_children.empty(); - } - - const std::list& getOrderedChildren() const { - return m_children; - } - - void removeChild(XMLObject* child); - - const XMLCh* getTextContent(unsigned int position=0) const { - return (m_text.size() > position) ? m_text[position] : NULL; - } - - void setTextContent(const XMLCh* value, unsigned int position=0); - - protected: - AbstractComplexElement() {} - - /** Copy constructor. */ - AbstractComplexElement(const AbstractComplexElement& src); - - /** - * Underlying list of child objects. - * Manages the lifetime of the children. - */ - std::list m_children; - - /** - * Interstitial text nodes. - * Needed to support mixed content, and preserve DOM whitespace across rebuilds. - */ - std::vector m_text; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_abscomplexel_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 xmltooling/AbstractComplexElement.h + * + * AbstractXMLObject mixin that implements children + */ + +#ifndef __xmltooling_abscomplexel_h__ +#define __xmltooling_abscomplexel_h__ + +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * AbstractXMLObject mixin that implements children. + * Inherit from this class to implement an element with child objects and mixed content. + */ + class XMLTOOL_API AbstractComplexElement : public virtual AbstractXMLObject + { + public: + virtual ~AbstractComplexElement(); + + bool hasChildren() const { + return !m_children.empty(); + } + + const std::list& getOrderedChildren() const { + return m_children; + } + + void removeChild(XMLObject* child); + + const XMLCh* getTextContent(unsigned int position=0) const { + return (m_text.size() > position) ? m_text[position] : NULL; + } + + void setTextContent(const XMLCh* value, unsigned int position=0); + + protected: + AbstractComplexElement() {} + + /** Copy constructor. */ + AbstractComplexElement(const AbstractComplexElement& src); + + /** + * Underlying list of child objects. + * Manages the lifetime of the children. + */ + std::list m_children; + + /** + * Interstitial text nodes. + * Needed to support mixed content, and preserve DOM whitespace across rebuilds. + */ + std::vector m_text; + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_abscomplexel_h__ */ diff --git a/xmltooling/AbstractDOMCachingXMLObject.cpp b/xmltooling/AbstractDOMCachingXMLObject.cpp index bee23c2..4966156 100644 --- a/xmltooling/AbstractDOMCachingXMLObject.cpp +++ b/xmltooling/AbstractDOMCachingXMLObject.cpp @@ -1,153 +1,153 @@ -/* - * 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. - */ - -/** - * AbstractDOMCachingXMLObject.cpp - * - * Extension of AbstractXMLObject that implements a DOMCachingXMLObject. - */ - -#include "internal.h" -#include "AbstractDOMCachingXMLObject.h" -#include "exceptions.h" -#include "XMLObjectBuilder.h" -#include "util/XMLHelper.h" - -#include -#include -#include - -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -AbstractDOMCachingXMLObject::~AbstractDOMCachingXMLObject() -{ - if (m_document) - m_document->release(); -} - -void AbstractDOMCachingXMLObject::setDOM(DOMElement* dom, bool bindDocument) const -{ - m_dom=dom; - if (dom) { - if (bindDocument) { - setDocument(dom->getOwnerDocument()); - } - } -} - -void AbstractDOMCachingXMLObject::releaseDOM() const -{ - if (m_dom) { - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".DOM"); - if (log.isDebugEnabled()) { - string qname=getElementQName().toString(); - log.debug("releasing cached DOM representation for (%s)", qname.empty() ? "unknown" : qname.c_str()); - } - setDOM(NULL); - } -} - -void AbstractDOMCachingXMLObject::releaseParentDOM(bool propagateRelease) const -{ - if (getParent() && getParent()->getDOM()) { - Category::getInstance(XMLTOOLING_LOGCAT".DOM").debug( - "releasing cached DOM representation for parent object with propagation set to %s", - propagateRelease ? "true" : "false" - ); - getParent()->releaseDOM(); - if (propagateRelease) - getParent()->releaseParentDOM(propagateRelease); - } -} - -class _release : public binary_function { -public: - void operator()(XMLObject* obj, bool propagate) const { - if (obj) { - obj->releaseDOM(); - if (propagate) - obj->releaseChildrenDOM(propagate); - } - } -}; - -void AbstractDOMCachingXMLObject::releaseChildrenDOM(bool propagateRelease) const -{ - if (hasChildren()) { - Category::getInstance(XMLTOOLING_LOGCAT".DOM").debug( - "releasing cached DOM representation for children with propagation set to %s", - propagateRelease ? "true" : "false" - ); - const list& children=getOrderedChildren(); - for_each(children.begin(),children.end(),bind2nd(_release(),propagateRelease)); - } -} - -DOMElement* AbstractDOMCachingXMLObject::cloneDOM(DOMDocument* doc) const -{ - if (getDOM()) { - if (!doc) - doc=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument(); - return static_cast(doc->importNode(getDOM(),true)); - } - return NULL; -} - -XMLObject* AbstractDOMCachingXMLObject::clone() const -{ - // See if we can clone via the DOM. - DOMElement* domCopy=cloneDOM(); - if (domCopy) { - // Seemed to work, so now we unmarshall the DOM to produce the clone. - const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(domCopy); - if (!b) { - auto_ptr q(XMLHelper::getNodeQName(domCopy)); - Category::getInstance(XMLTOOLING_LOGCAT".DOM").error( - "DOM clone failed, unable to locate builder for element (%s)", q->toString().c_str() - ); - domCopy->getOwnerDocument()->release(); - throw UnmarshallingException("Unable to locate builder for cloned element."); - } - XercesJanitor janitor(domCopy->getOwnerDocument()); - XMLObject* ret = b->buildFromElement(domCopy,true); // bind document - janitor.release(); // safely transferred - return ret; - } - return NULL; -} - -void AbstractDOMCachingXMLObject::detach() -{ - // This is an override that duplicates some of the checking in the base class but - // adds document management in preparation for deletion of the parent. - - if (!getParent()) - return; - - if (getParent()->hasParent()) - throw XMLObjectException("Cannot detach an object whose parent is itself a child."); - - AbstractDOMCachingXMLObject* parent = dynamic_cast(getParent()); - if (parent && parent->m_document) { - // Transfer control of document to me... - setDocument(parent->m_document); - parent->m_document = NULL; - } - // The rest is done by the base. - AbstractXMLObject::detach(); -} +/* + * 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. + */ + +/** + * AbstractDOMCachingXMLObject.cpp + * + * Extension of AbstractXMLObject that implements a DOMCachingXMLObject. + */ + +#include "internal.h" +#include "AbstractDOMCachingXMLObject.h" +#include "exceptions.h" +#include "XMLObjectBuilder.h" +#include "util/XMLHelper.h" + +#include +#include +#include + +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +AbstractDOMCachingXMLObject::~AbstractDOMCachingXMLObject() +{ + if (m_document) + m_document->release(); +} + +void AbstractDOMCachingXMLObject::setDOM(DOMElement* dom, bool bindDocument) const +{ + m_dom=dom; + if (dom) { + if (bindDocument) { + setDocument(dom->getOwnerDocument()); + } + } +} + +void AbstractDOMCachingXMLObject::releaseDOM() const +{ + if (m_dom) { + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".DOM"); + if (log.isDebugEnabled()) { + string qname=getElementQName().toString(); + log.debug("releasing cached DOM representation for (%s)", qname.empty() ? "unknown" : qname.c_str()); + } + setDOM(NULL); + } +} + +void AbstractDOMCachingXMLObject::releaseParentDOM(bool propagateRelease) const +{ + if (getParent() && getParent()->getDOM()) { + Category::getInstance(XMLTOOLING_LOGCAT".DOM").debug( + "releasing cached DOM representation for parent object with propagation set to %s", + propagateRelease ? "true" : "false" + ); + getParent()->releaseDOM(); + if (propagateRelease) + getParent()->releaseParentDOM(propagateRelease); + } +} + +class _release : public binary_function { +public: + void operator()(XMLObject* obj, bool propagate) const { + if (obj) { + obj->releaseDOM(); + if (propagate) + obj->releaseChildrenDOM(propagate); + } + } +}; + +void AbstractDOMCachingXMLObject::releaseChildrenDOM(bool propagateRelease) const +{ + if (hasChildren()) { + Category::getInstance(XMLTOOLING_LOGCAT".DOM").debug( + "releasing cached DOM representation for children with propagation set to %s", + propagateRelease ? "true" : "false" + ); + const list& children=getOrderedChildren(); + for_each(children.begin(),children.end(),bind2nd(_release(),propagateRelease)); + } +} + +DOMElement* AbstractDOMCachingXMLObject::cloneDOM(DOMDocument* doc) const +{ + if (getDOM()) { + if (!doc) + doc=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument(); + return static_cast(doc->importNode(getDOM(),true)); + } + return NULL; +} + +XMLObject* AbstractDOMCachingXMLObject::clone() const +{ + // See if we can clone via the DOM. + DOMElement* domCopy=cloneDOM(); + if (domCopy) { + // Seemed to work, so now we unmarshall the DOM to produce the clone. + const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(domCopy); + if (!b) { + auto_ptr q(XMLHelper::getNodeQName(domCopy)); + Category::getInstance(XMLTOOLING_LOGCAT".DOM").error( + "DOM clone failed, unable to locate builder for element (%s)", q->toString().c_str() + ); + domCopy->getOwnerDocument()->release(); + throw UnmarshallingException("Unable to locate builder for cloned element."); + } + XercesJanitor janitor(domCopy->getOwnerDocument()); + XMLObject* ret = b->buildFromElement(domCopy,true); // bind document + janitor.release(); // safely transferred + return ret; + } + return NULL; +} + +void AbstractDOMCachingXMLObject::detach() +{ + // This is an override that duplicates some of the checking in the base class but + // adds document management in preparation for deletion of the parent. + + if (!getParent()) + return; + + if (getParent()->hasParent()) + throw XMLObjectException("Cannot detach an object whose parent is itself a child."); + + AbstractDOMCachingXMLObject* parent = dynamic_cast(getParent()); + if (parent && parent->m_document) { + // Transfer control of document to me... + setDocument(parent->m_document); + parent->m_document = NULL; + } + // The rest is done by the base. + AbstractXMLObject::detach(); +} diff --git a/xmltooling/AbstractDOMCachingXMLObject.h b/xmltooling/AbstractDOMCachingXMLObject.h index 1e357b9..94a9e56 100644 --- a/xmltooling/AbstractDOMCachingXMLObject.h +++ b/xmltooling/AbstractDOMCachingXMLObject.h @@ -1,92 +1,92 @@ -/* - * 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 AbstractDOMCachingXMLObject.h - * - * AbstractXMLObject mixin that implements DOM caching - */ - -#if !defined(__xmltooling_abstractdomxmlobj_h__) -#define __xmltooling_abstractdomxmlobj_h__ - -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * AbstractXMLObject mixin that implements DOM caching. - * Inherit from this class to implement standard DOM caching behavior. - */ - class XMLTOOL_API AbstractDOMCachingXMLObject : public virtual AbstractXMLObject - { - public: - virtual ~AbstractDOMCachingXMLObject(); - - DOMElement* getDOM() const { - return m_dom; - } - - void setDOM(DOMElement* dom, bool bindDocument=false) const; - - void setDocument(DOMDocument* doc) const { - if (m_document) - m_document->release(); - m_document=doc; - } - - virtual void releaseDOM() const; - - virtual void releaseParentDOM(bool propagateRelease=true) const; - - virtual void releaseChildrenDOM(bool propagateRelease=true) const; - - XMLObject* clone() const; - - void detach(); - - protected: - AbstractDOMCachingXMLObject() : m_dom(NULL), m_document(NULL) {} - - /** Copy constructor. */ - AbstractDOMCachingXMLObject(const AbstractDOMCachingXMLObject& src) - : AbstractXMLObject(src), m_dom(NULL), m_document(NULL) {} - - /** - * If a DOM representation exists, this clones it into a new document. - * - * @param doc the document to clone into, or NULL, in which case a new document is created - * @return the cloned DOM - */ - DOMElement* cloneDOM(DOMDocument* doc=NULL) const; - - private: - mutable DOMElement* m_dom; - mutable DOMDocument* m_document; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_abstractdomxmlobj_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 AbstractDOMCachingXMLObject.h + * + * AbstractXMLObject mixin that implements DOM caching + */ + +#if !defined(__xmltooling_abstractdomxmlobj_h__) +#define __xmltooling_abstractdomxmlobj_h__ + +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * AbstractXMLObject mixin that implements DOM caching. + * Inherit from this class to implement standard DOM caching behavior. + */ + class XMLTOOL_API AbstractDOMCachingXMLObject : public virtual AbstractXMLObject + { + public: + virtual ~AbstractDOMCachingXMLObject(); + + DOMElement* getDOM() const { + return m_dom; + } + + void setDOM(DOMElement* dom, bool bindDocument=false) const; + + void setDocument(DOMDocument* doc) const { + if (m_document) + m_document->release(); + m_document=doc; + } + + virtual void releaseDOM() const; + + virtual void releaseParentDOM(bool propagateRelease=true) const; + + virtual void releaseChildrenDOM(bool propagateRelease=true) const; + + XMLObject* clone() const; + + void detach(); + + protected: + AbstractDOMCachingXMLObject() : m_dom(NULL), m_document(NULL) {} + + /** Copy constructor. */ + AbstractDOMCachingXMLObject(const AbstractDOMCachingXMLObject& src) + : AbstractXMLObject(src), m_dom(NULL), m_document(NULL) {} + + /** + * If a DOM representation exists, this clones it into a new document. + * + * @param doc the document to clone into, or NULL, in which case a new document is created + * @return the cloned DOM + */ + DOMElement* cloneDOM(DOMDocument* doc=NULL) const; + + private: + mutable DOMElement* m_dom; + mutable DOMDocument* m_document; + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_abstractdomxmlobj_h__ */ diff --git a/xmltooling/AbstractElementProxy.h b/xmltooling/AbstractElementProxy.h index ed95e53..473a942 100644 --- a/xmltooling/AbstractElementProxy.h +++ b/xmltooling/AbstractElementProxy.h @@ -1,67 +1,67 @@ -/* - * 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 xmltooling/AbstractElementProxy.h - * - * AbstractXMLObject mixin that implements an open content model - */ - -#ifndef __xmltooling_abseleproxy_h__ -#define __xmltooling_abseleproxy_h__ - -#include -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * AbstractXMLObject mixin that layers ElementProxy on top of a complex element. - * Inherit from this class to implement complex content - * and expose the underlying child collection in read/write mode. - */ - class XMLTOOL_API AbstractElementProxy : public virtual ElementProxy, public AbstractComplexElement - { - public: - virtual ~AbstractElementProxy() {} - - virtual ListOf(XMLObject) getXMLObjects() { - return ListOf(XMLObject)(this,m_children,NULL,m_children.end()); - } - - virtual const std::list& getXMLObjects() const { - return m_children; - } - - protected: - AbstractElementProxy() {} - - /** Copy constructor. */ - AbstractElementProxy(const AbstractElementProxy& src) : AbstractXMLObject(src), AbstractComplexElement(src) {} - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_abseleproxy_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 xmltooling/AbstractElementProxy.h + * + * AbstractXMLObject mixin that implements an open content model + */ + +#ifndef __xmltooling_abseleproxy_h__ +#define __xmltooling_abseleproxy_h__ + +#include +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * AbstractXMLObject mixin that layers ElementProxy on top of a complex element. + * Inherit from this class to implement complex content + * and expose the underlying child collection in read/write mode. + */ + class XMLTOOL_API AbstractElementProxy : public virtual ElementProxy, public AbstractComplexElement + { + public: + virtual ~AbstractElementProxy() {} + + virtual ListOf(XMLObject) getXMLObjects() { + return ListOf(XMLObject)(this,m_children,NULL,m_children.end()); + } + + virtual const std::list& getXMLObjects() const { + return m_children; + } + + protected: + AbstractElementProxy() {} + + /** Copy constructor. */ + AbstractElementProxy(const AbstractElementProxy& src) : AbstractXMLObject(src), AbstractComplexElement(src) {} + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_abseleproxy_h__ */ diff --git a/xmltooling/AbstractSimpleElement.cpp b/xmltooling/AbstractSimpleElement.cpp index 920aa3b..90fb717 100644 --- a/xmltooling/AbstractSimpleElement.cpp +++ b/xmltooling/AbstractSimpleElement.cpp @@ -1,36 +1,36 @@ -/* - * 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. - */ - -/** - * AbstractSimpleElement.cpp - * - * Extension of AbstractXMLObject that implements simple elements - */ - -#include "internal.h" -#include "AbstractSimpleElement.h" - -using namespace xmltooling; -using namespace std; - -// shared "empty" list of children for childless objects - -list AbstractSimpleElement::m_no_children; - -void AbstractSimpleElement::removeChild(XMLObject* child) -{ - throw XMLObjectException("Cannot remove child from a childless object."); -} +/* + * 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. + */ + +/** + * AbstractSimpleElement.cpp + * + * Extension of AbstractXMLObject that implements simple elements + */ + +#include "internal.h" +#include "AbstractSimpleElement.h" + +using namespace xmltooling; +using namespace std; + +// shared "empty" list of children for childless objects + +list AbstractSimpleElement::m_no_children; + +void AbstractSimpleElement::removeChild(XMLObject* child) +{ + throw XMLObjectException("Cannot remove child from a childless object."); +} diff --git a/xmltooling/AbstractSimpleElement.h b/xmltooling/AbstractSimpleElement.h index 86e0e80..b034533 100644 --- a/xmltooling/AbstractSimpleElement.h +++ b/xmltooling/AbstractSimpleElement.h @@ -1,85 +1,85 @@ -/* - * 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 xmltooling/AbstractSimpleElement.h - * - * AbstractXMLObject mixin that implements a simple string-based content model - */ - -#ifndef __xmltooling_abssimpleel_h__ -#define __xmltooling_abssimpleel_h__ - -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * AbstractXMLObject mixin that implements a simple string-based content model. - * Inherit from this class to support string-based element content. - */ - class XMLTOOL_API AbstractSimpleElement : public virtual AbstractXMLObject - { - public: - virtual ~AbstractSimpleElement() { - XMLString::release(&m_value); - } - - bool hasChildren() const { - return false; - } - - const std::list& getOrderedChildren() const { - return m_no_children; - } - - void removeChild(XMLObject* child); - - virtual const XMLCh* getTextContent(unsigned int position=0) const { - return (position==0) ? m_value : NULL; - } - - virtual void setTextContent(const XMLCh* value, unsigned int position=0) { - if (position > 0) - throw XMLObjectException("Cannot set text content in simple element at position > 0."); - m_value=prepareForAssignment(m_value,value); - } - - protected: - AbstractSimpleElement() : m_value(NULL) {} - - /** Copy constructor. */ - AbstractSimpleElement(const AbstractSimpleElement& src) - : AbstractXMLObject(src), m_value(XMLString::replicate(src.m_value)) {} - - private: - XMLCh* m_value; - - static std::list m_no_children; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_abssimpleel_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 xmltooling/AbstractSimpleElement.h + * + * AbstractXMLObject mixin that implements a simple string-based content model + */ + +#ifndef __xmltooling_abssimpleel_h__ +#define __xmltooling_abssimpleel_h__ + +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * AbstractXMLObject mixin that implements a simple string-based content model. + * Inherit from this class to support string-based element content. + */ + class XMLTOOL_API AbstractSimpleElement : public virtual AbstractXMLObject + { + public: + virtual ~AbstractSimpleElement() { + XMLString::release(&m_value); + } + + bool hasChildren() const { + return false; + } + + const std::list& getOrderedChildren() const { + return m_no_children; + } + + void removeChild(XMLObject* child); + + virtual const XMLCh* getTextContent(unsigned int position=0) const { + return (position==0) ? m_value : NULL; + } + + virtual void setTextContent(const XMLCh* value, unsigned int position=0) { + if (position > 0) + throw XMLObjectException("Cannot set text content in simple element at position > 0."); + m_value=prepareForAssignment(m_value,value); + } + + protected: + AbstractSimpleElement() : m_value(NULL) {} + + /** Copy constructor. */ + AbstractSimpleElement(const AbstractSimpleElement& src) + : AbstractXMLObject(src), m_value(XMLString::replicate(src.m_value)) {} + + private: + XMLCh* m_value; + + static std::list m_no_children; + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_abssimpleel_h__ */ diff --git a/xmltooling/AbstractXMLObject.cpp b/xmltooling/AbstractXMLObject.cpp index e019f4e..21ec488 100644 --- a/xmltooling/AbstractXMLObject.cpp +++ b/xmltooling/AbstractXMLObject.cpp @@ -1,151 +1,151 @@ -/* -* 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(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType) - : m_log(&log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")), m_schemaLocation(NULL), - 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_schemaLocation(XMLString::replicate(src.m_schemaLocation)), - m_parent(NULL), m_elementQname(src.m_elementQname), m_typeQname(NULL) -{ - if (src.m_typeQname) - m_typeQname=new QName(*src.m_typeQname); -} - -XMLCh* AbstractXMLObject::prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue) -{ - if (!XMLString::equals(oldValue,newValue)) { - releaseThisandParentDOM(); - XMLCh* newString = XMLString::replicate(newValue); - XMLString::release(&oldValue); - return newString; - } - return oldValue; -} - -QName* AbstractXMLObject::prepareForAssignment(QName* oldValue, const QName* newValue) -{ - if (!oldValue) { - if (newValue) { - releaseThisandParentDOM(); - Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix()); - addNamespace(newNamespace); - return new QName(*newValue); - } - return NULL; - } - - delete oldValue; - releaseThisandParentDOM(); - if (newValue) { - Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix()); - addNamespace(newNamespace); - return new QName(*newValue); - } - return NULL; -} - -DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const DateTime* newValue) -{ - if (!oldValue) { - if (newValue) { - releaseThisandParentDOM(); - return new DateTime(*newValue); - } - return NULL; - } - - delete oldValue; - releaseThisandParentDOM(); - return newValue ? new DateTime(*newValue) : NULL; -} - -DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, time_t newValue) -{ - delete oldValue; - releaseThisandParentDOM(); - DateTime* ret = new DateTime(newValue); - ret->parseDateTime(); - return ret; -} - -DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const XMLCh* newValue) -{ - delete oldValue; - releaseThisandParentDOM(); - DateTime* ret = new DateTime(newValue); - ret->parseDateTime(); - return ret; -} - -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; - } - - if (oldValue != newValue) { - delete oldValue; - releaseThisandParentDOM(); - if (newValue) - newValue->setParent(this); - } - - return newValue; -} - -void AbstractXMLObject::detach() -{ - if (!getParent()) - return; - else if (getParent()->hasParent()) - throw XMLObjectException("Cannot detach an object whose parent is itself a child."); - - // Pull ourselves out of the parent and then blast him. - getParent()->removeChild(this); - delete m_parent; - m_parent = NULL; -} +/* +* 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(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType) + : m_log(&log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")), m_schemaLocation(NULL), + 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_schemaLocation(XMLString::replicate(src.m_schemaLocation)), + m_parent(NULL), m_elementQname(src.m_elementQname), m_typeQname(NULL) +{ + if (src.m_typeQname) + m_typeQname=new QName(*src.m_typeQname); +} + +XMLCh* AbstractXMLObject::prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue) +{ + if (!XMLString::equals(oldValue,newValue)) { + releaseThisandParentDOM(); + XMLCh* newString = XMLString::replicate(newValue); + XMLString::release(&oldValue); + return newString; + } + return oldValue; +} + +QName* AbstractXMLObject::prepareForAssignment(QName* oldValue, const QName* newValue) +{ + if (!oldValue) { + if (newValue) { + releaseThisandParentDOM(); + Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix()); + addNamespace(newNamespace); + return new QName(*newValue); + } + return NULL; + } + + delete oldValue; + releaseThisandParentDOM(); + if (newValue) { + Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix()); + addNamespace(newNamespace); + return new QName(*newValue); + } + return NULL; +} + +DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const DateTime* newValue) +{ + if (!oldValue) { + if (newValue) { + releaseThisandParentDOM(); + return new DateTime(*newValue); + } + return NULL; + } + + delete oldValue; + releaseThisandParentDOM(); + return newValue ? new DateTime(*newValue) : NULL; +} + +DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, time_t newValue) +{ + delete oldValue; + releaseThisandParentDOM(); + DateTime* ret = new DateTime(newValue); + ret->parseDateTime(); + return ret; +} + +DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const XMLCh* newValue) +{ + delete oldValue; + releaseThisandParentDOM(); + DateTime* ret = new DateTime(newValue); + ret->parseDateTime(); + return ret; +} + +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; + } + + if (oldValue != newValue) { + delete oldValue; + releaseThisandParentDOM(); + if (newValue) + newValue->setParent(this); + } + + return newValue; +} + +void AbstractXMLObject::detach() +{ + if (!getParent()) + return; + else if (getParent()->hasParent()) + throw XMLObjectException("Cannot detach an object whose parent is itself a child."); + + // Pull ourselves out of the parent and then blast him. + getParent()->removeChild(this); + delete m_parent; + m_parent = NULL; +} diff --git a/xmltooling/AbstractXMLObject.h b/xmltooling/AbstractXMLObject.h index 3f2e801..80f3871 100644 --- a/xmltooling/AbstractXMLObject.h +++ b/xmltooling/AbstractXMLObject.h @@ -1,214 +1,214 @@ -/* -* 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 AbstractXMLObject.h - * - * An abstract implementation of XMLObject. - */ - -#if !defined(__xmltooling_abstractxmlobj_h__) -#define __xmltooling_abstractxmlobj_h__ - -#include -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * An abstract implementation of XMLObject. - * This is the primary concrete base class, and supplies basic namespace, - * type, and parent handling. Most implementation classes should not - * directly inherit from this class, but rather from the various mixins - * that supply the rest of the XMLObject interface, as required. - */ - class XMLTOOL_API AbstractXMLObject : public virtual XMLObject - { - public: - virtual ~AbstractXMLObject() { - delete m_typeQname; - XMLString::release(&m_schemaLocation); - } - - void detach(); - - const QName& getElementQName() const { - return m_elementQname; - } - - const std::set& getNamespaces() const { - return m_namespaces; - } - - void addNamespace(const Namespace& ns) const { - std::set::iterator i = m_namespaces.find(ns); - if (i == m_namespaces.end()) - m_namespaces.insert(ns); - else if (ns.alwaysDeclare()) - i->setAlwaysDeclare(true); - } - - void removeNamespace(const Namespace& ns) { - m_namespaces.erase(ns); - } - - const QName* getSchemaType() const { - return m_typeQname; - } - - const XMLCh* getXMLID() const { - return NULL; - } - - bool hasParent() const { - return m_parent != NULL; - } - - XMLObject* getParent() const { - return m_parent; - } - - void setParent(XMLObject* parent) { - m_parent = parent; - } - - protected: - /** - * Constructor - * - * @param nsURI the namespace of the element - * @param localName the local name of the XML element this Object represents - * @param prefix the namespace prefix to use - * @param schemaType the xsi:type to use - */ - AbstractXMLObject( - const XMLCh* nsURI=NULL, const XMLCh* localName=NULL, const XMLCh* prefix=NULL, const QName* schemaType=NULL - ); - - /** Copy constructor. */ - AbstractXMLObject(const AbstractXMLObject& src); - - /** - * A helper function for derived classes, for assignment of strings. - * - * This 'normalizes' newString, and then if it is different from oldString, - * it invalidates the DOM, frees the old string, and returns the new. - * If not different, it frees the new string and just returns the old value. - * - * @param oldValue - the current value - * @param newValue - the new value - * - * @return the value that should be assigned - */ - XMLCh* prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue); - - /** - * A helper function for derived classes, for assignment of date/time data. - * - * It invalidates the DOM, frees the old object, and returns the new. - * - * @param oldValue - the current value - * @param newValue - the new value - * - * @return the value that should be assigned - */ - DateTime* prepareForAssignment(DateTime* oldValue, const DateTime* newValue); - - /** - * A helper function for derived classes, for assignment of date/time data. - * - * It invalidates the DOM, frees the old object, and returns the new. - * - * @param oldValue - the current value - * @param newValue - the epoch to assign as the new value - * - * @return the value that should be assigned - */ - DateTime* prepareForAssignment(DateTime* oldValue, time_t newValue); - - /** - * A helper function for derived classes, for assignment of date/time data. - * - * It invalidates the DOM, frees the old object, and returns the new. - * - * @param oldValue - the current value - * @param newValue - the new value in string form - * - * @return the value that should be assigned - */ - DateTime* prepareForAssignment(DateTime* oldValue, const XMLCh* newValue); - - /** - * A helper function for derived classes, for assignment of QName data. - * - * It invalidates the DOM, frees the old object, and returns the new. - * - * @param oldValue - the current value - * @param newValue - the new value - * - * @return the value that should be assigned - */ - QName* prepareForAssignment(QName* oldValue, const QName* newValue); - - /** - * A helper function for derived classes, for assignment of (singleton) XML objects. - * - * It is indifferent to whether either the old or the new version of the value is null. - * This method will do a safe compare of the objects and will also invalidate the DOM if appropriate. - * Note that since the new value (even if NULL) is always returned, it may be more efficient - * to discard the return value and just assign independently if a dynamic cast would be involved. - * - * @param oldValue - current value - * @param newValue - proposed new value - * @return the new value - * - * @throws XMLObjectException if the new child already has a parent. - */ - XMLObject* prepareForAssignment(XMLObject* oldValue, XMLObject* newValue); - - /** - * Set of namespaces associated with the object. - */ - mutable std::set m_namespaces; - - /** - * Logging object. - */ - void* m_log; - - /** - * Stores off xsi:schemaLocation attribute. - */ - XMLCh* m_schemaLocation; - - private: - XMLObject* m_parent; - QName m_elementQname; - QName* m_typeQname; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_abstractxmlobj_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 AbstractXMLObject.h + * + * An abstract implementation of XMLObject. + */ + +#if !defined(__xmltooling_abstractxmlobj_h__) +#define __xmltooling_abstractxmlobj_h__ + +#include +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * An abstract implementation of XMLObject. + * This is the primary concrete base class, and supplies basic namespace, + * type, and parent handling. Most implementation classes should not + * directly inherit from this class, but rather from the various mixins + * that supply the rest of the XMLObject interface, as required. + */ + class XMLTOOL_API AbstractXMLObject : public virtual XMLObject + { + public: + virtual ~AbstractXMLObject() { + delete m_typeQname; + XMLString::release(&m_schemaLocation); + } + + void detach(); + + const QName& getElementQName() const { + return m_elementQname; + } + + const std::set& getNamespaces() const { + return m_namespaces; + } + + void addNamespace(const Namespace& ns) const { + std::set::iterator i = m_namespaces.find(ns); + if (i == m_namespaces.end()) + m_namespaces.insert(ns); + else if (ns.alwaysDeclare()) + const_cast(*i).setAlwaysDeclare(true); + } + + void removeNamespace(const Namespace& ns) { + m_namespaces.erase(ns); + } + + const QName* getSchemaType() const { + return m_typeQname; + } + + const XMLCh* getXMLID() const { + return NULL; + } + + bool hasParent() const { + return m_parent != NULL; + } + + XMLObject* getParent() const { + return m_parent; + } + + void setParent(XMLObject* parent) { + m_parent = parent; + } + + protected: + /** + * Constructor + * + * @param nsURI the namespace of the element + * @param localName the local name of the XML element this Object represents + * @param prefix the namespace prefix to use + * @param schemaType the xsi:type to use + */ + AbstractXMLObject( + const XMLCh* nsURI=NULL, const XMLCh* localName=NULL, const XMLCh* prefix=NULL, const QName* schemaType=NULL + ); + + /** Copy constructor. */ + AbstractXMLObject(const AbstractXMLObject& src); + + /** + * A helper function for derived classes, for assignment of strings. + * + * This 'normalizes' newString, and then if it is different from oldString, + * it invalidates the DOM, frees the old string, and returns the new. + * If not different, it frees the new string and just returns the old value. + * + * @param oldValue - the current value + * @param newValue - the new value + * + * @return the value that should be assigned + */ + XMLCh* prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue); + + /** + * A helper function for derived classes, for assignment of date/time data. + * + * It invalidates the DOM, frees the old object, and returns the new. + * + * @param oldValue - the current value + * @param newValue - the new value + * + * @return the value that should be assigned + */ + DateTime* prepareForAssignment(DateTime* oldValue, const DateTime* newValue); + + /** + * A helper function for derived classes, for assignment of date/time data. + * + * It invalidates the DOM, frees the old object, and returns the new. + * + * @param oldValue - the current value + * @param newValue - the epoch to assign as the new value + * + * @return the value that should be assigned + */ + DateTime* prepareForAssignment(DateTime* oldValue, time_t newValue); + + /** + * A helper function for derived classes, for assignment of date/time data. + * + * It invalidates the DOM, frees the old object, and returns the new. + * + * @param oldValue - the current value + * @param newValue - the new value in string form + * + * @return the value that should be assigned + */ + DateTime* prepareForAssignment(DateTime* oldValue, const XMLCh* newValue); + + /** + * A helper function for derived classes, for assignment of QName data. + * + * It invalidates the DOM, frees the old object, and returns the new. + * + * @param oldValue - the current value + * @param newValue - the new value + * + * @return the value that should be assigned + */ + QName* prepareForAssignment(QName* oldValue, const QName* newValue); + + /** + * A helper function for derived classes, for assignment of (singleton) XML objects. + * + * It is indifferent to whether either the old or the new version of the value is null. + * This method will do a safe compare of the objects and will also invalidate the DOM if appropriate. + * Note that since the new value (even if NULL) is always returned, it may be more efficient + * to discard the return value and just assign independently if a dynamic cast would be involved. + * + * @param oldValue - current value + * @param newValue - proposed new value + * @return the new value + * + * @throws XMLObjectException if the new child already has a parent. + */ + XMLObject* prepareForAssignment(XMLObject* oldValue, XMLObject* newValue); + + /** + * Set of namespaces associated with the object. + */ + mutable std::set m_namespaces; + + /** + * Logging object. + */ + void* m_log; + + /** + * Stores off xsi:schemaLocation attribute. + */ + XMLCh* m_schemaLocation; + + private: + XMLObject* m_parent; + QName m_elementQname; + QName* m_typeQname; + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_abstractxmlobj_h__ */ diff --git a/xmltooling/AttributeExtensibleXMLObject.h b/xmltooling/AttributeExtensibleXMLObject.h index 87bc6d3..05377f1 100644 --- a/xmltooling/AttributeExtensibleXMLObject.h +++ b/xmltooling/AttributeExtensibleXMLObject.h @@ -1,127 +1,127 @@ -/* - * 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 AttributeExtensibleXMLObject.h - * - * An XMLObject that supports arbitrary attributes - */ - -#if !defined(__xmltooling_attrextxmlobj_h__) -#define __xmltooling_attrextxmlobj_h__ - -#include - -using namespace xercesc; - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * An XMLObject that supports arbitrary attributes. - */ - class XMLTOOL_API AttributeExtensibleXMLObject : public virtual XMLObject - { - protected: - AttributeExtensibleXMLObject() {} - - public: - virtual ~AttributeExtensibleXMLObject() {} - - /** - * Gets the value of an XML attribute of the object. - * - * @param qualifiedName qualified name of the attribute - * @return the attribute value, or NULL - */ - virtual const XMLCh* getAttribute(const QName& qualifiedName) const=0; - - /** - * Sets (or clears) an XML attribute of the object. - * - * @param qualifiedName qualified name of the attribute - * @param value value to set, or NULL to clear - * @param ID true iff the attribute is an XML ID - */ - virtual void setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID=false)=0; - - /** - * Gets an immutable map of the extended XML attributes of the object. - * - * This set is not guaranteed to (and generally will not) include - * attributes defined directly on the object's "type". - */ - virtual const std::map& getExtensionAttributes() const=0; - - /** - * Gets an immutable list of all the ID attributes currently registered. - * - * @return list of all the ID attributes currently registered - */ - static const std::set& getRegisteredIDAttributes() { - return m_idAttributeSet; - } - - /** - * Tests whether an XML attribute is registered as an XML ID. - * - * @return true iff the attribute name matches a registered XML ID attribute - */ - static bool isRegisteredIDAttribute(const QName& name) { - return m_idAttributeSet.find(name)!=m_idAttributeSet.end(); - } - - /** - * Registers a new attribute as being of XML ID type. - * - * @param name the qualified attribute name - */ - static void registerIDAttribute(const QName& name) { - m_idAttributeSet.insert(name); - } - - /** - * Deregisters an ID attribute. - * - * @param name the qualified attribute name - */ - static void deregisterIDAttribute(const QName& name) { - m_idAttributeSet.erase(name); - } - - /** - * Deregisters all ID attributes. - */ - static void deregisterIDAttributes() { - m_idAttributeSet.clear(); - } - - private: - /** Set of attributes to treat as XML IDs. */ - static std::set m_idAttributeSet; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_attrextxmlobj_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 AttributeExtensibleXMLObject.h + * + * An XMLObject that supports arbitrary attributes + */ + +#if !defined(__xmltooling_attrextxmlobj_h__) +#define __xmltooling_attrextxmlobj_h__ + +#include + +using namespace xercesc; + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * An XMLObject that supports arbitrary attributes. + */ + class XMLTOOL_API AttributeExtensibleXMLObject : public virtual XMLObject + { + protected: + AttributeExtensibleXMLObject() {} + + public: + virtual ~AttributeExtensibleXMLObject() {} + + /** + * Gets the value of an XML attribute of the object. + * + * @param qualifiedName qualified name of the attribute + * @return the attribute value, or NULL + */ + virtual const XMLCh* getAttribute(const QName& qualifiedName) const=0; + + /** + * Sets (or clears) an XML attribute of the object. + * + * @param qualifiedName qualified name of the attribute + * @param value value to set, or NULL to clear + * @param ID true iff the attribute is an XML ID + */ + virtual void setAttribute(const QName& qualifiedName, const XMLCh* value, bool ID=false)=0; + + /** + * Gets an immutable map of the extended XML attributes of the object. + * + * This set is not guaranteed to (and generally will not) include + * attributes defined directly on the object's "type". + */ + virtual const std::map& getExtensionAttributes() const=0; + + /** + * Gets an immutable list of all the ID attributes currently registered. + * + * @return list of all the ID attributes currently registered + */ + static const std::set& getRegisteredIDAttributes() { + return m_idAttributeSet; + } + + /** + * Tests whether an XML attribute is registered as an XML ID. + * + * @return true iff the attribute name matches a registered XML ID attribute + */ + static bool isRegisteredIDAttribute(const QName& name) { + return m_idAttributeSet.find(name)!=m_idAttributeSet.end(); + } + + /** + * Registers a new attribute as being of XML ID type. + * + * @param name the qualified attribute name + */ + static void registerIDAttribute(const QName& name) { + m_idAttributeSet.insert(name); + } + + /** + * Deregisters an ID attribute. + * + * @param name the qualified attribute name + */ + static void deregisterIDAttribute(const QName& name) { + m_idAttributeSet.erase(name); + } + + /** + * Deregisters all ID attributes. + */ + static void deregisterIDAttributes() { + m_idAttributeSet.clear(); + } + + private: + /** Set of attributes to treat as XML IDs. */ + static std::set m_idAttributeSet; + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_attrextxmlobj_h__ */ diff --git a/xmltooling/ElementProxy.h b/xmltooling/ElementProxy.h index a10d873..6b5c44e 100644 --- a/xmltooling/ElementProxy.h +++ b/xmltooling/ElementProxy.h @@ -1,59 +1,59 @@ -/* - * 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 xmltooling/ElementProxy.h - * - * An XMLObject with an open content model - */ - -#ifndef __xmltooling_eleproxy_h__ -#define __xmltooling_eleproxy_h__ - -#include -#include - -using namespace xercesc; - -namespace xmltooling { - - /** - * An XMLObject that exposes its children via mutable list. - */ - class XMLTOOL_API ElementProxy : public virtual XMLObject - { - public: - ElementProxy() {} - virtual ~ElementProxy() {} - - /** - * Gets a mutable list of child objects - * - * @return mutable list of child objects - */ - virtual ListOf(XMLObject) getXMLObjects()=0; - - /** - * Gets an immutable list of child objects - * - * @return immutable list of child objects - */ - virtual const std::list& getXMLObjects() const=0; - }; - -}; - -#endif /* __xmltooling_eleproxy_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 xmltooling/ElementProxy.h + * + * An XMLObject with an open content model + */ + +#ifndef __xmltooling_eleproxy_h__ +#define __xmltooling_eleproxy_h__ + +#include +#include + +using namespace xercesc; + +namespace xmltooling { + + /** + * An XMLObject that exposes its children via mutable list. + */ + class XMLTOOL_API ElementProxy : public virtual XMLObject + { + public: + ElementProxy() {} + virtual ~ElementProxy() {} + + /** + * Gets a mutable list of child objects + * + * @return mutable list of child objects + */ + virtual ListOf(XMLObject) getXMLObjects()=0; + + /** + * Gets an immutable list of child objects + * + * @return immutable list of child objects + */ + virtual const std::list& getXMLObjects() const=0; + }; + +}; + +#endif /* __xmltooling_eleproxy_h__ */ diff --git a/xmltooling/Lockable.h b/xmltooling/Lockable.h index 0047a94..42d4b47 100644 --- a/xmltooling/Lockable.h +++ b/xmltooling/Lockable.h @@ -1,101 +1,101 @@ -/* - * 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 Lockable.h - * - * Locking abstraction - */ - -#ifndef __xmltooling_lockable_h__ -#define __xmltooling_lockable_h__ - -#include - -namespace xmltooling { - - /** - * Abstract mixin interface for interfaces that support locking - */ - struct XMLTOOL_API Lockable - { - virtual ~Lockable() {} - - /** - * Lock the associated object for exclusive access. - * - * @return a pointer to the object being locked - */ - virtual Lockable* lock()=0; - - /** - * Unlock the associated object from exclusive access. - */ - virtual void unlock()=0; - }; - - /** - * RAII wrapper for lockable objects to ensure lock release - */ - class XMLTOOL_API Locker - { - MAKE_NONCOPYABLE(Locker); - public: - /** - * Optionally locks an object and stores it for later release. - * - * @param lockee pointer to an object to hold, and optionally lock - * @param lock true iff object is not yet locked - */ - Locker(Lockable* lockee=NULL, bool lock=true) { - if (lockee && lock) - m_lockee=lockee->lock(); - else - m_lockee=lockee; - } - - /** - * Optionally locks an object and stores it for later release. - * If an object is already held, it is unlocked and detached. - * - * @param lockee pointer to an object to hold, and optionally lock - * @param lock true iff object is not yet locked - */ - void assign(Lockable* lockee=NULL, bool lock=true) { - if (m_lockee) - m_lockee->unlock(); - m_lockee=NULL; - if (lockee && lock) - m_lockee=lockee->lock(); - else - m_lockee=lockee; - } - - /** - * Destructor releases lock on held pointer, if any. - */ - ~Locker() { - if (m_lockee) - m_lockee->unlock(); - } - - private: - Lockable* m_lockee; - }; - -}; - -#endif /* __xmltooling_lockable_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 Lockable.h + * + * Locking abstraction + */ + +#ifndef __xmltooling_lockable_h__ +#define __xmltooling_lockable_h__ + +#include + +namespace xmltooling { + + /** + * Abstract mixin interface for interfaces that support locking + */ + struct XMLTOOL_API Lockable + { + virtual ~Lockable() {} + + /** + * Lock the associated object for exclusive access. + * + * @return a pointer to the object being locked + */ + virtual Lockable* lock()=0; + + /** + * Unlock the associated object from exclusive access. + */ + virtual void unlock()=0; + }; + + /** + * RAII wrapper for lockable objects to ensure lock release + */ + class XMLTOOL_API Locker + { + MAKE_NONCOPYABLE(Locker); + public: + /** + * Optionally locks an object and stores it for later release. + * + * @param lockee pointer to an object to hold, and optionally lock + * @param lock true iff object is not yet locked + */ + Locker(Lockable* lockee=NULL, bool lock=true) { + if (lockee && lock) + m_lockee=lockee->lock(); + else + m_lockee=lockee; + } + + /** + * Optionally locks an object and stores it for later release. + * If an object is already held, it is unlocked and detached. + * + * @param lockee pointer to an object to hold, and optionally lock + * @param lock true iff object is not yet locked + */ + void assign(Lockable* lockee=NULL, bool lock=true) { + if (m_lockee) + m_lockee->unlock(); + m_lockee=NULL; + if (lockee && lock) + m_lockee=lockee->lock(); + else + m_lockee=lockee; + } + + /** + * Destructor releases lock on held pointer, if any. + */ + ~Locker() { + if (m_lockee) + m_lockee->unlock(); + } + + private: + Lockable* m_lockee; + }; + +}; + +#endif /* __xmltooling_lockable_h__ */ diff --git a/xmltooling/Namespace.cpp b/xmltooling/Namespace.cpp index 21bf4b2..3369aa1 100644 --- a/xmltooling/Namespace.cpp +++ b/xmltooling/Namespace.cpp @@ -1,105 +1,105 @@ -/* - * 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. - */ - -/** - * Namespace.cpp - * - * Representing XML namespace attributes - */ - -#include "internal.h" -#include "Namespace.h" - -using namespace xmltooling; - -Namespace::Namespace(const XMLCh* uri, const XMLCh* prefix, bool alwaysDeclare) : m_pinned(alwaysDeclare) -{ -#ifndef HAVE_GOOD_STL - m_uri=m_prefix=NULL; -#endif - setNamespaceURI(uri); - setNamespacePrefix(prefix); -} - -Namespace::~Namespace() -{ -#ifndef HAVE_GOOD_STL - XMLString::release(&m_uri); - XMLString::release(&m_prefix); -#endif -} - -void Namespace::setNamespacePrefix(const XMLCh* prefix) -{ -#ifdef HAVE_GOOD_STL - if (prefix) - m_prefix=prefix; - else - m_prefix.erase(); -#else - if (m_prefix) - XMLString::release(&m_prefix); - m_prefix=XMLString::replicate(prefix); -#endif -} - -void Namespace::setNamespaceURI(const XMLCh* uri) -{ -#ifdef HAVE_GOOD_STL - if (uri) - m_uri=uri; - else - m_uri.erase(); -#else - if (m_uri) - XMLString::release(&m_uri); - m_uri=XMLString::replicate(uri); -#endif -} - -#ifndef HAVE_GOOD_STL -Namespace::Namespace(const Namespace& src) -{ - m_uri=XMLString::replicate(src.getNamespaceURI()); - m_prefix=XMLString::replicate(src.getNamespacePrefix()); - m_pinned=src.getAlwaysDeclare(); -} - -Namespace& Namespace::operator=(const Namespace& src) -{ - m_uri=XMLString::replicate(src.getNamespaceURI()); - m_prefix=XMLString::replicate(src.getNamespacePrefix()); - m_pinned=src.getAlwaysDeclare(); - return *this; -} - -bool xmltooling::operator==(const Namespace& op1, const Namespace& op2) -{ - return (XMLString::equals(op1.getNamespaceURI(),op2.getNamespaceURI()) && - XMLString::equals(op1.getNamespacePrefix(),op2.getNamespacePrefix())); -} -#endif - -bool xmltooling::operator<(const Namespace& op1, const Namespace& op2) -{ - int i=XMLString::compareString(op1.getNamespaceURI(),op2.getNamespaceURI()); - if (i<0) - return true; - else if (i==0) - return (XMLString::compareString(op1.getNamespacePrefix(),op2.getNamespacePrefix())<0); - else - return false; -} +/* + * 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. + */ + +/** + * Namespace.cpp + * + * Representing XML namespace attributes + */ + +#include "internal.h" +#include "Namespace.h" + +using namespace xmltooling; + +Namespace::Namespace(const XMLCh* uri, const XMLCh* prefix, bool alwaysDeclare) : m_pinned(alwaysDeclare) +{ +#ifndef HAVE_GOOD_STL + m_uri=m_prefix=NULL; +#endif + setNamespaceURI(uri); + setNamespacePrefix(prefix); +} + +Namespace::~Namespace() +{ +#ifndef HAVE_GOOD_STL + XMLString::release(&m_uri); + XMLString::release(&m_prefix); +#endif +} + +void Namespace::setNamespacePrefix(const XMLCh* prefix) +{ +#ifdef HAVE_GOOD_STL + if (prefix) + m_prefix=prefix; + else + m_prefix.erase(); +#else + if (m_prefix) + XMLString::release(&m_prefix); + m_prefix=XMLString::replicate(prefix); +#endif +} + +void Namespace::setNamespaceURI(const XMLCh* uri) +{ +#ifdef HAVE_GOOD_STL + if (uri) + m_uri=uri; + else + m_uri.erase(); +#else + if (m_uri) + XMLString::release(&m_uri); + m_uri=XMLString::replicate(uri); +#endif +} + +#ifndef HAVE_GOOD_STL +Namespace::Namespace(const Namespace& src) +{ + m_uri=XMLString::replicate(src.getNamespaceURI()); + m_prefix=XMLString::replicate(src.getNamespacePrefix()); + m_pinned=src.getAlwaysDeclare(); +} + +Namespace& Namespace::operator=(const Namespace& src) +{ + m_uri=XMLString::replicate(src.getNamespaceURI()); + m_prefix=XMLString::replicate(src.getNamespacePrefix()); + m_pinned=src.getAlwaysDeclare(); + return *this; +} + +bool xmltooling::operator==(const Namespace& op1, const Namespace& op2) +{ + return (XMLString::equals(op1.getNamespaceURI(),op2.getNamespaceURI()) && + XMLString::equals(op1.getNamespacePrefix(),op2.getNamespacePrefix())); +} +#endif + +bool xmltooling::operator<(const Namespace& op1, const Namespace& op2) +{ + int i=XMLString::compareString(op1.getNamespaceURI(),op2.getNamespaceURI()); + if (i<0) + return true; + else if (i==0) + return (XMLString::compareString(op1.getNamespacePrefix(),op2.getNamespacePrefix())<0); + else + return false; +} diff --git a/xmltooling/Namespace.h b/xmltooling/Namespace.h index 3e9bfc8..1177693 100644 --- a/xmltooling/Namespace.h +++ b/xmltooling/Namespace.h @@ -1,140 +1,140 @@ -/* - * 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 Namespace.h - * - * Representing XML namespace attributes - */ - -#if !defined(__xmltooling_namespace_h__) -#define __xmltooling_namespace_h__ - -#include - -namespace xmltooling { - - /** - * A data structure for encapsulating XML Namespace attributes - */ - class XMLTOOL_API Namespace - { - public: - /** - * Constructor - * @param uri namespace URI - * @param prefix namespace prefix (without the colon) - * @param alwaysDeclare true iff the namespace should always be declared regardless of in-scope declarations - */ - Namespace(const XMLCh* uri=NULL, const XMLCh* prefix=NULL, bool alwaysDeclare=false); - - ~Namespace(); -#ifndef HAVE_GOOD_STL - /** - * Deep copy constructor - */ - Namespace(const Namespace& src); - - /** - * Deep assignment operator - */ - Namespace& operator=(const Namespace& src); -#endif - -#ifdef HAVE_GOOD_STL - /** - * Returns the namespace prefix - * @return Null-terminated Unicode string containing the prefix, without the colon - */ - const XMLCh* getNamespacePrefix() const { return m_prefix.c_str(); } - - /** - * Returns the namespace URI - * @return Null-terminated Unicode string containing the URI - */ - const XMLCh* getNamespaceURI() const { return m_uri.c_str(); } -#else - /** - * Returns the namespace prefix - * @return Null-terminated Unicode string containing the prefix, without the colon - */ - const XMLCh* getNamespacePrefix() const { return m_prefix; } - - /** - * Returns the namespace URI - * @return Null-terminated Unicode string containing the URI - */ - const XMLCh* getNamespaceURI() const { return m_uri; } -#endif - - /** - * Returns true iff the namespace should always be declared regardless of in-scope declarations - * @return the alwaysDeclared setting - */ - const bool alwaysDeclare() const { return m_pinned; } - - /** - * Sets the namespace prefix - * @param prefix Null-terminated Unicode string containing the prefix, without the colon - */ - void setNamespacePrefix(const XMLCh* prefix); - - /** - * Sets the namespace URI - * @param uri Null-terminated Unicode string containing the URI - */ - void setNamespaceURI(const XMLCh* uri); - - /** - * Sets the alwaysDeclared property - * @param alwaysDeclare true iff the namespace should always be declared regardless of in-scope declarations - */ - void setAlwaysDeclare(bool alwaysDeclare) { m_pinned = alwaysDeclare; } - - private: - bool m_pinned; -#ifdef HAVE_GOOD_STL - xstring m_uri; - xstring m_prefix; -#else - XMLCh* m_uri; - XMLCh* m_prefix; -#endif - }; - - /** - * Returns true iff op1's namespace lexically compares less than op2's namespace, - * or if equal, iff op1's prefix lexically compares less than op2's prefix. - * - * Needed for use with sorted STL containers. - * - * @param op1 First namspace to compare - * @param op2 Second namespace to compare - */ - extern XMLTOOL_API bool operator<(const Namespace& op1, const Namespace& op2); - -#ifndef HAVE_GOOD_STL - /** - * Returns true iff op1's namespace and prefix are equal to op2's namespace and prefix. - * @param op1 First namspace to compare - * @param op2 Second namespace to compare - */ - extern XMLTOOL_API bool operator==(const Namespace& op1, const Namespace& op2); -#endif - -}; - -#endif /* __xmltooling_namespace_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 Namespace.h + * + * Representing XML namespace attributes + */ + +#if !defined(__xmltooling_namespace_h__) +#define __xmltooling_namespace_h__ + +#include + +namespace xmltooling { + + /** + * A data structure for encapsulating XML Namespace attributes + */ + class XMLTOOL_API Namespace + { + public: + /** + * Constructor + * @param uri namespace URI + * @param prefix namespace prefix (without the colon) + * @param alwaysDeclare true iff the namespace should always be declared regardless of in-scope declarations + */ + Namespace(const XMLCh* uri=NULL, const XMLCh* prefix=NULL, bool alwaysDeclare=false); + + ~Namespace(); +#ifndef HAVE_GOOD_STL + /** + * Deep copy constructor + */ + Namespace(const Namespace& src); + + /** + * Deep assignment operator + */ + Namespace& operator=(const Namespace& src); +#endif + +#ifdef HAVE_GOOD_STL + /** + * Returns the namespace prefix + * @return Null-terminated Unicode string containing the prefix, without the colon + */ + const XMLCh* getNamespacePrefix() const { return m_prefix.c_str(); } + + /** + * Returns the namespace URI + * @return Null-terminated Unicode string containing the URI + */ + const XMLCh* getNamespaceURI() const { return m_uri.c_str(); } +#else + /** + * Returns the namespace prefix + * @return Null-terminated Unicode string containing the prefix, without the colon + */ + const XMLCh* getNamespacePrefix() const { return m_prefix; } + + /** + * Returns the namespace URI + * @return Null-terminated Unicode string containing the URI + */ + const XMLCh* getNamespaceURI() const { return m_uri; } +#endif + + /** + * Returns true iff the namespace should always be declared regardless of in-scope declarations + * @return the alwaysDeclared setting + */ + const bool alwaysDeclare() const { return m_pinned; } + + /** + * Sets the namespace prefix + * @param prefix Null-terminated Unicode string containing the prefix, without the colon + */ + void setNamespacePrefix(const XMLCh* prefix); + + /** + * Sets the namespace URI + * @param uri Null-terminated Unicode string containing the URI + */ + void setNamespaceURI(const XMLCh* uri); + + /** + * Sets the alwaysDeclared property + * @param alwaysDeclare true iff the namespace should always be declared regardless of in-scope declarations + */ + void setAlwaysDeclare(bool alwaysDeclare) { m_pinned = alwaysDeclare; } + + private: + bool m_pinned; +#ifdef HAVE_GOOD_STL + xstring m_uri; + xstring m_prefix; +#else + XMLCh* m_uri; + XMLCh* m_prefix; +#endif + }; + + /** + * Returns true iff op1's namespace lexically compares less than op2's namespace, + * or if equal, iff op1's prefix lexically compares less than op2's prefix. + * + * Needed for use with sorted STL containers. + * + * @param op1 First namspace to compare + * @param op2 Second namespace to compare + */ + extern XMLTOOL_API bool operator<(const Namespace& op1, const Namespace& op2); + +#ifndef HAVE_GOOD_STL + /** + * Returns true iff op1's namespace and prefix are equal to op2's namespace and prefix. + * @param op1 First namspace to compare + * @param op2 Second namespace to compare + */ + extern XMLTOOL_API bool operator==(const Namespace& op1, const Namespace& op2); +#endif + +}; + +#endif /* __xmltooling_namespace_h__ */ diff --git a/xmltooling/PluginManager.h b/xmltooling/PluginManager.h index 5f248e0..f882891 100644 --- a/xmltooling/PluginManager.h +++ b/xmltooling/PluginManager.h @@ -1,108 +1,108 @@ -/* - * 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 xmltooling/PluginManager.h - * - * Plugin management template - */ - -#ifndef __xmltooling_plugin_h__ -#define __xmltooling_plugin_h__ - -#include -#include - -#include -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * Template for management/access to plugins constructed based on a string type - * and arbitrary parameters. - * - * @param T class of plugin to manage - * @param Params parameters for plugin construction - */ - template class PluginManager - { - public: - PluginManager() {} - ~PluginManager() {} - - /** Factory function for plugin. */ - typedef T* Factory(const Params&); - - /** - * Registers the factory for a given type. - * - * @param type the name of the plugin type - * @param factory the factory function for the plugin type - */ - void registerFactory(const std::string& type, typename PluginManager::Factory* factory) { - if (!type.empty() && factory) - m_map[type]=factory; - } - - /** - * Unregisters the factory for a given type. - * - * @param type the name of the plugin type - */ - void deregisterFactory(const std::string& type) { - if (!type.empty()) - m_map.erase(type); - } - - /** - * Unregisters all registered factories. - */ - void deregisterFactories() { - m_map.clear(); - } - - /** - * Builds a new instance of a plugin of a given type, configuring it - * with the supplied parameters. - * - * @param type the name of the plugin type - * @param p parameters to configure plugin - * @return the constructed plugin - */ - T* newPlugin(const std::string& type, const Params& p) { - typename std::map::const_iterator i=m_map.find(type); - if (i==m_map.end()) - throw UnknownExtensionException("Unable to build plugin of type '$1'",params(1,type.c_str())); - return i->second(p); - } - - private: - std::map m_map; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_plugin_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 xmltooling/PluginManager.h + * + * Plugin management template + */ + +#ifndef __xmltooling_plugin_h__ +#define __xmltooling_plugin_h__ + +#include +#include + +#include +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * Template for management/access to plugins constructed based on a string type + * and arbitrary parameters. + * + * @param T class of plugin to manage + * @param Params parameters for plugin construction + */ + template class PluginManager + { + public: + PluginManager() {} + ~PluginManager() {} + + /** Factory function for plugin. */ + typedef T* Factory(const Params&); + + /** + * Registers the factory for a given type. + * + * @param type the name of the plugin type + * @param factory the factory function for the plugin type + */ + void registerFactory(const std::string& type, typename PluginManager::Factory* factory) { + if (!type.empty() && factory) + m_map[type]=factory; + } + + /** + * Unregisters the factory for a given type. + * + * @param type the name of the plugin type + */ + void deregisterFactory(const std::string& type) { + if (!type.empty()) + m_map.erase(type); + } + + /** + * Unregisters all registered factories. + */ + void deregisterFactories() { + m_map.clear(); + } + + /** + * Builds a new instance of a plugin of a given type, configuring it + * with the supplied parameters. + * + * @param type the name of the plugin type + * @param p parameters to configure plugin + * @return the constructed plugin + */ + T* newPlugin(const std::string& type, const Params& p) { + typename std::map::const_iterator i=m_map.find(type); + if (i==m_map.end()) + throw UnknownExtensionException("Unable to build plugin of type '$1'",params(1,type.c_str())); + return i->second(p); + } + + private: + std::map m_map; + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_plugin_h__ */ diff --git a/xmltooling/QName.cpp b/xmltooling/QName.cpp index 6ca7f79..a54fcca 100644 --- a/xmltooling/QName.cpp +++ b/xmltooling/QName.cpp @@ -1,144 +1,144 @@ -/* - * 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. - */ - -/** - * QName.cpp - * - * Representing XML QNames - */ - -#include "internal.h" -#include "QName.h" - -using namespace xmltooling; -using namespace std; - -QName::QName(const XMLCh* uri, const XMLCh* localPart, const XMLCh* prefix) -{ -#ifndef HAVE_GOOD_STL - m_uri=m_prefix=m_local=NULL; -#endif - setNamespaceURI(uri); - setLocalPart(localPart); - setPrefix(prefix); -} - -QName::~QName() -{ -#ifndef HAVE_GOOD_STL - XMLString::release(&m_uri); - XMLString::release(&m_prefix); - XMLString::release(&m_local); -#endif -} - -void QName::setPrefix(const XMLCh* prefix) -{ -#ifdef HAVE_GOOD_STL - if (prefix) - m_prefix=prefix; - else - m_prefix.erase(); -#else - if (m_prefix) - XMLString::release(&m_prefix); - m_prefix=XMLString::replicate(prefix); -#endif -} - -void QName::setNamespaceURI(const XMLCh* uri) -{ -#ifdef HAVE_GOOD_STL - if (uri) - m_uri=uri; - else - m_uri.erase(); -#else - if (m_uri) - XMLString::release(&m_uri); - m_uri=XMLString::replicate(uri); -#endif -} - -void QName::setLocalPart(const XMLCh* localPart) -{ -#ifdef HAVE_GOOD_STL - if (localPart) - m_local=localPart; - else - m_local.erase(); -#else - if (m_local) - XMLString::release(&m_local); - m_local=XMLString::replicate(localPart); -#endif -} - -#ifndef HAVE_GOOD_STL -QName::QName(const QName& src) -{ - m_uri=XMLString::replicate(src.getNamespaceURI()); - m_prefix=XMLString::replicate(src.getPrefix()); - m_local=XMLString::replicate(src.getLocalPart()); -} - -QName& QName::operator=(const QName& src) -{ - m_uri=XMLString::replicate(src.getNamespaceURI()); - m_prefix=XMLString::replicate(src.getPrefix()); - m_local=XMLString::replicate(src.getLocalPart()); - return *this; -} -#endif - -bool xmltooling::operator==(const QName& op1, const QName& op2) -{ - return (!XMLString::compareString(op1.getNamespaceURI(),op2.getNamespaceURI()) && - !XMLString::compareString(op1.getLocalPart(),op2.getLocalPart())); -} - -bool xmltooling::operator!=(const QName& op1, const QName& op2) -{ - return !(op1==op2); -} - -bool xmltooling::operator<(const QName& op1, const QName& op2) -{ - int i=XMLString::compareString(op1.getNamespaceURI(),op2.getNamespaceURI()); - if (i<0) - return true; - else if (i==0) - return (XMLString::compareString(op1.getLocalPart(),op2.getLocalPart())<0); - else - return false; -} - -string QName::toString() const -{ - if (!hasLocalPart()) - return ""; - auto_ptr_char local(getLocalPart()); - if (hasPrefix()) { - auto_ptr_char pre(getPrefix()); - return string(pre.get()) + ':' + local.get(); - } - else if (hasNamespaceURI()) { - auto_ptr_char ns(getNamespaceURI()); - return string("{") + ns.get() + '}' + local.get(); - } - else - return local.get(); -} +/* + * 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. + */ + +/** + * QName.cpp + * + * Representing XML QNames + */ + +#include "internal.h" +#include "QName.h" + +using namespace xmltooling; +using namespace std; + +QName::QName(const XMLCh* uri, const XMLCh* localPart, const XMLCh* prefix) +{ +#ifndef HAVE_GOOD_STL + m_uri=m_prefix=m_local=NULL; +#endif + setNamespaceURI(uri); + setLocalPart(localPart); + setPrefix(prefix); +} + +QName::~QName() +{ +#ifndef HAVE_GOOD_STL + XMLString::release(&m_uri); + XMLString::release(&m_prefix); + XMLString::release(&m_local); +#endif +} + +void QName::setPrefix(const XMLCh* prefix) +{ +#ifdef HAVE_GOOD_STL + if (prefix) + m_prefix=prefix; + else + m_prefix.erase(); +#else + if (m_prefix) + XMLString::release(&m_prefix); + m_prefix=XMLString::replicate(prefix); +#endif +} + +void QName::setNamespaceURI(const XMLCh* uri) +{ +#ifdef HAVE_GOOD_STL + if (uri) + m_uri=uri; + else + m_uri.erase(); +#else + if (m_uri) + XMLString::release(&m_uri); + m_uri=XMLString::replicate(uri); +#endif +} + +void QName::setLocalPart(const XMLCh* localPart) +{ +#ifdef HAVE_GOOD_STL + if (localPart) + m_local=localPart; + else + m_local.erase(); +#else + if (m_local) + XMLString::release(&m_local); + m_local=XMLString::replicate(localPart); +#endif +} + +#ifndef HAVE_GOOD_STL +QName::QName(const QName& src) +{ + m_uri=XMLString::replicate(src.getNamespaceURI()); + m_prefix=XMLString::replicate(src.getPrefix()); + m_local=XMLString::replicate(src.getLocalPart()); +} + +QName& QName::operator=(const QName& src) +{ + m_uri=XMLString::replicate(src.getNamespaceURI()); + m_prefix=XMLString::replicate(src.getPrefix()); + m_local=XMLString::replicate(src.getLocalPart()); + return *this; +} +#endif + +bool xmltooling::operator==(const QName& op1, const QName& op2) +{ + return (!XMLString::compareString(op1.getNamespaceURI(),op2.getNamespaceURI()) && + !XMLString::compareString(op1.getLocalPart(),op2.getLocalPart())); +} + +bool xmltooling::operator!=(const QName& op1, const QName& op2) +{ + return !(op1==op2); +} + +bool xmltooling::operator<(const QName& op1, const QName& op2) +{ + int i=XMLString::compareString(op1.getNamespaceURI(),op2.getNamespaceURI()); + if (i<0) + return true; + else if (i==0) + return (XMLString::compareString(op1.getLocalPart(),op2.getLocalPart())<0); + else + return false; +} + +string QName::toString() const +{ + if (!hasLocalPart()) + return ""; + auto_ptr_char local(getLocalPart()); + if (hasPrefix()) { + auto_ptr_char pre(getPrefix()); + return string(pre.get()) + ':' + local.get(); + } + else if (hasNamespaceURI()) { + auto_ptr_char ns(getNamespaceURI()); + return string("{") + ns.get() + '}' + local.get(); + } + else + return local.get(); +} diff --git a/xmltooling/QName.h b/xmltooling/QName.h index c26e900..ac17d27 100644 --- a/xmltooling/QName.h +++ b/xmltooling/QName.h @@ -1,198 +1,198 @@ -/* - * 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 QName.h - * - * Representing XML QNames - */ - -#if !defined(__xmltooling_qname_h__) -#define __xmltooling_qname_h__ - -#include -#include - -namespace xmltooling { - - /** - * A data structure for encapsulating XML QNames. - * The Xerces class is too limited to use at the moment. - */ - class XMLTOOL_API QName - { - public: - /** - * Constructor - * @param uri namespace URI - * @param localPart local name - * @param prefix namespace prefix (without the colon) - */ - QName(const XMLCh* uri=NULL, const XMLCh* localPart=NULL, const XMLCh* prefix=NULL); - - ~QName(); -#ifndef HAVE_GOOD_STL - /** - * Deep copy constructor - */ - QName(const QName& src); - - /** - * Deep assignment operator - */ - QName& operator=(const QName& src); -#endif - -#ifdef HAVE_GOOD_STL - /** - * Indicates whether the QName has a prefix. - * @return true iff the prefix is non-empty - */ - bool hasPrefix() const { return !m_prefix.empty(); } - - /** - * Indicates whether the QName has a non-empty namespace. - * @return true iff the namespace is non-empty - */ - bool hasNamespaceURI() const { return !m_uri.empty(); } - - /** - * Indicates whether the QName has a non-empty local name. - * @return true iff the local name is non-empty - */ - bool hasLocalPart() const { return !m_local.empty(); } - - /** - * Returns the namespace prefix - * @return Null-terminated Unicode string containing the prefix, without the colon - */ - const XMLCh* getPrefix() const { return m_prefix.c_str(); } - - /** - * Returns the namespace URI - * @return Null-terminated Unicode string containing the URI - */ - const XMLCh* getNamespaceURI() const { return m_uri.c_str(); } - - /** - * Returns the local part of the name - * @return Null-terminated Unicode string containing the local name - */ - const XMLCh* getLocalPart() const { return m_local.c_str(); } -#else - /** - * Indicates whether the QName has a prefix. - * @return true iff the prefix is non-empty - */ - bool hasPrefix() const { return m_prefix && *m_prefix; } - - /** - * Indicates whether the QName has a non-empty namespace. - * @return true iff the namespace is non-empty - */ - bool hasNamespaceURI() const { return m_uri && *m_uri; } - - /** - * Indicates whether the QName has a non-empty local name. - * @return true iff the local name is non-empty - */ - bool hasLocalPart() const { return m_local && *m_local; } - - /** - * Returns the namespace prefix - * @return Null-terminated Unicode string containing the prefix, without the colon - */ - const XMLCh* getPrefix() const { return m_prefix; } - - /** - * Returns the namespace URI - * @return Null-terminated Unicode string containing the URI - */ - const XMLCh* getNamespaceURI() const { return m_uri; } - - /** - * Returns the local part of the name - * @return Null-terminated Unicode string containing the local name - */ - const XMLCh* getLocalPart() const { return m_local; } -#endif - - /** - * Sets the namespace prefix - * @param prefix Null-terminated Unicode string containing the prefix, without the colon - */ - void setPrefix(const XMLCh* prefix); - - /** - * Sets the namespace URI - * @param uri Null-terminated Unicode string containing the URI - */ - void setNamespaceURI(const XMLCh* uri); - - /** - * Sets the local part of the name - * @param localPart Null-terminated Unicode string containing the local name - */ - void setLocalPart(const XMLCh* localPart); - - /** - * Gets a string representation of the QName for logging, etc. - * Format is prefix:localPart or {namespaceURI}localPart if no prefix. - * - * @return the string representation - */ - std::string toString() const; - - private: -#ifdef HAVE_GOOD_STL - xstring m_uri; - xstring m_local; - xstring m_prefix; -#else - XMLCh* m_uri; - XMLCh* m_local; - XMLCh* m_prefix; -#endif - }; - - /** - * Returns true iff op1's namespace lexically compares less than op2's namespace, - * or if equal, iff op1's prefix lexically compares less than op2's prefix. - * - * Needed for use with sorted STL containers. - * - * @param op1 First qname to compare - * @param op2 Second qname to compare - */ - extern XMLTOOL_API bool operator<(const QName& op1, const QName& op2); - - /** - * Returns true iff op1's components are equal to op2's components, excluding prefix. - * @param op1 First qname to compare - * @param op2 Second qname to compare - */ - extern XMLTOOL_API bool operator==(const QName& op1, const QName& op2); - - /** - * Returns true iff op1's components are not equal to op2's components, excluding prefix. - * @param op1 First qname to compare - * @param op2 Second qname to compare - */ - extern XMLTOOL_API bool operator!=(const QName& op1, const QName& op2); - -}; - -#endif /* __xmltooling_qname_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 QName.h + * + * Representing XML QNames + */ + +#if !defined(__xmltooling_qname_h__) +#define __xmltooling_qname_h__ + +#include +#include + +namespace xmltooling { + + /** + * A data structure for encapsulating XML QNames. + * The Xerces class is too limited to use at the moment. + */ + class XMLTOOL_API QName + { + public: + /** + * Constructor + * @param uri namespace URI + * @param localPart local name + * @param prefix namespace prefix (without the colon) + */ + QName(const XMLCh* uri=NULL, const XMLCh* localPart=NULL, const XMLCh* prefix=NULL); + + ~QName(); +#ifndef HAVE_GOOD_STL + /** + * Deep copy constructor + */ + QName(const QName& src); + + /** + * Deep assignment operator + */ + QName& operator=(const QName& src); +#endif + +#ifdef HAVE_GOOD_STL + /** + * Indicates whether the QName has a prefix. + * @return true iff the prefix is non-empty + */ + bool hasPrefix() const { return !m_prefix.empty(); } + + /** + * Indicates whether the QName has a non-empty namespace. + * @return true iff the namespace is non-empty + */ + bool hasNamespaceURI() const { return !m_uri.empty(); } + + /** + * Indicates whether the QName has a non-empty local name. + * @return true iff the local name is non-empty + */ + bool hasLocalPart() const { return !m_local.empty(); } + + /** + * Returns the namespace prefix + * @return Null-terminated Unicode string containing the prefix, without the colon + */ + const XMLCh* getPrefix() const { return m_prefix.c_str(); } + + /** + * Returns the namespace URI + * @return Null-terminated Unicode string containing the URI + */ + const XMLCh* getNamespaceURI() const { return m_uri.c_str(); } + + /** + * Returns the local part of the name + * @return Null-terminated Unicode string containing the local name + */ + const XMLCh* getLocalPart() const { return m_local.c_str(); } +#else + /** + * Indicates whether the QName has a prefix. + * @return true iff the prefix is non-empty + */ + bool hasPrefix() const { return m_prefix && *m_prefix; } + + /** + * Indicates whether the QName has a non-empty namespace. + * @return true iff the namespace is non-empty + */ + bool hasNamespaceURI() const { return m_uri && *m_uri; } + + /** + * Indicates whether the QName has a non-empty local name. + * @return true iff the local name is non-empty + */ + bool hasLocalPart() const { return m_local && *m_local; } + + /** + * Returns the namespace prefix + * @return Null-terminated Unicode string containing the prefix, without the colon + */ + const XMLCh* getPrefix() const { return m_prefix; } + + /** + * Returns the namespace URI + * @return Null-terminated Unicode string containing the URI + */ + const XMLCh* getNamespaceURI() const { return m_uri; } + + /** + * Returns the local part of the name + * @return Null-terminated Unicode string containing the local name + */ + const XMLCh* getLocalPart() const { return m_local; } +#endif + + /** + * Sets the namespace prefix + * @param prefix Null-terminated Unicode string containing the prefix, without the colon + */ + void setPrefix(const XMLCh* prefix); + + /** + * Sets the namespace URI + * @param uri Null-terminated Unicode string containing the URI + */ + void setNamespaceURI(const XMLCh* uri); + + /** + * Sets the local part of the name + * @param localPart Null-terminated Unicode string containing the local name + */ + void setLocalPart(const XMLCh* localPart); + + /** + * Gets a string representation of the QName for logging, etc. + * Format is prefix:localPart or {namespaceURI}localPart if no prefix. + * + * @return the string representation + */ + std::string toString() const; + + private: +#ifdef HAVE_GOOD_STL + xstring m_uri; + xstring m_local; + xstring m_prefix; +#else + XMLCh* m_uri; + XMLCh* m_local; + XMLCh* m_prefix; +#endif + }; + + /** + * Returns true iff op1's namespace lexically compares less than op2's namespace, + * or if equal, iff op1's prefix lexically compares less than op2's prefix. + * + * Needed for use with sorted STL containers. + * + * @param op1 First qname to compare + * @param op2 Second qname to compare + */ + extern XMLTOOL_API bool operator<(const QName& op1, const QName& op2); + + /** + * Returns true iff op1's components are equal to op2's components, excluding prefix. + * @param op1 First qname to compare + * @param op2 Second qname to compare + */ + extern XMLTOOL_API bool operator==(const QName& op1, const QName& op2); + + /** + * Returns true iff op1's components are not equal to op2's components, excluding prefix. + * @param op1 First qname to compare + * @param op2 Second qname to compare + */ + extern XMLTOOL_API bool operator!=(const QName& op1, const QName& op2); + +}; + +#endif /* __xmltooling_qname_h__ */ diff --git a/xmltooling/XMLObject.h b/xmltooling/XMLObject.h index 1fb26d6..fc9225e 100644 --- a/xmltooling/XMLObject.h +++ b/xmltooling/XMLObject.h @@ -1,321 +1,321 @@ -/* - * 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 XMLObject.h - * - * Abstract interface to objects that can be manipulated in and out of XML form. - */ - -#ifndef __xmltooling_xmlobj_h__ -#define __xmltooling_xmlobj_h__ - -#include -#include -#include -#include -#include -#include - -using namespace xercesc; - -#ifndef XMLTOOLING_NO_XMLSEC -namespace xmlsignature { - class XMLTOOL_API Signature; -}; -#endif - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * Object that represents an XML Element that has been unmarshalled into this C++ object. - */ - class XMLTOOL_API XMLObject - { - public: - virtual ~XMLObject() {} - - /** - * Creates a copy of the object, along with all of its children. - * - * The new object tree will be completely distinct and independent of - * the original in all respects. - */ - virtual XMLObject* clone() const=0; - - /** - * Specialized function for detaching a child object from its parent - * while disposing of the parent. - * - * This is not a generic way of detaching any child object, but only of - * pruning a single child from the root of an XMLObject tree. If the - * detached XMLObject's parent is itself a child, an exception will be - * thrown. It's mainly useful for turning a child into the new root of - * the tree without having to clone the child. - */ - virtual void detach()=0; - - /** - * Gets the QName for this element. This QName MUST - * contain the namespace URI, namespace prefix, and local element name. - * - * @return constant reference to the QName for this object - */ - virtual const QName& getElementQName() const=0; - - /** - * Gets the namespaces that are scoped to this element. - * - * The caller MUST NOT modify the set returned, but may use any - * non-modifying operations or algorithms on it. Iterators will - * remain valid unless the set member referenced is removed using - * the removeNamespace method. - * - * @return the namespaces that are scoped to this element - */ - virtual const std::set& getNamespaces() const=0; - - /** - * Adds a namespace to the ones already scoped to this element - * - * @param ns the namespace to add - */ - virtual void addNamespace(const Namespace& ns) const=0; - - /** - * Removes a namespace from this element - * - * @param ns the namespace to remove - */ - virtual void removeNamespace(const Namespace& ns)=0; - - /** - * Gets the XML schema type of this element. This translates to contents the xsi:type - * attribute for the element. - * - * @return XML schema type of this element - */ - virtual const QName* getSchemaType() const=0; - - /** - * Gets the value of the ID attribute set on this object, if any. - * - * @return an ID value or NULL - */ - virtual const XMLCh* getXMLID() const=0; - - /** - * Checks to see if this object has a parent. - * - * @return true if the object has a parent, false if not - */ - virtual bool hasParent() const=0; - - /** - * Gets the parent of this element or null if there is no parent. - * - * @return the parent of this element or null - */ - virtual XMLObject* getParent() const=0; - - /** - * Sets the parent of this element. - * - * @param parent the parent of this element - */ - virtual void setParent(XMLObject* parent)=0; - - /** - * Checks if this XMLObject has children. - * - * @return true if this XMLObject has children, false if not - */ - virtual bool hasChildren() const=0; - - /** - * Returns an unmodifiable list of child objects in the order that they - * should appear in the serialized representation. - * - * The validity of the returned list is not maintained if any non-const - * operations are performed on the parent object. - * - * @return the list of children - */ - virtual const std::list& getOrderedChildren() const=0; - - /** - * Used by a child's detach method to isolate the child from - * this parent object in preparation for destroying the parent - * (this object). - * - * @param child the child object to remove - */ - virtual void removeChild(XMLObject* child)=0; - - /** - * Returns the text content at the specified position relative to - * any child elements. A zero represents leading text, 1 comes after - * the first child, and so forth. - * - * @param position the relative child element position of the text - * @return the designated text value - */ - virtual const XMLCh* getTextContent(unsigned int position=0) const=0; - - /** - * Sets (or clears) text content relative to a child element's position. - * - * @param value value to set, or NULL to clear - * @param position position relative to child element - */ - virtual void setTextContent(const XMLCh* value, unsigned int position=0)=0; - - /** - * Gets the DOM representation of this XMLObject, if one exists. - * - * @return the DOM representation of this XMLObject - */ - virtual DOMElement* getDOM() const=0; - - /** - * Sets the DOM representation of this XMLObject. - * - * @param dom DOM representation of this XMLObject - * @param bindDocument true if the object should take ownership of the associated Document - */ - virtual void setDOM(DOMElement* dom, bool bindDocument=false) const=0; - - /** - * Assigns ownership of a DOM document to the XMLObject. - * This binds the lifetime of the document to the lifetime of the object. - * - * @param doc DOM document bound to this object - */ - virtual void setDocument(DOMDocument* doc) const=0; - - /** - * Releases the DOM representation of this XMLObject, if there is one. - */ - virtual void releaseDOM() const=0; - - /** - * Releases the DOM representation of this XMLObject's parent. - * - * @param propagateRelease true if all ancestors of this element should release their DOM - */ - virtual void releaseParentDOM(bool propagateRelease=true) const=0; - - /** - * Releases the DOM representation of this XMLObject's children. - * - * @param propagateRelease true if all descendants of this element should release their DOM - */ - virtual void releaseChildrenDOM(bool propagateRelease=true) const=0; - - /** - * A convenience method that is equal to calling releaseDOM() then releaseParentDOM(true). - */ - void releaseThisandParentDOM() const { - if (getDOM()) { - releaseDOM(); - releaseParentDOM(true); - } - } - - /** - * A convenience method that is equal to calling releaseChildrenDOM(true) then releaseDOM(). - */ - void releaseThisAndChildrenDOM() const { - if (getDOM()) { - releaseChildrenDOM(true); - releaseDOM(); - } - } - - /** - * Marshalls the XMLObject, and its children, into a DOM element. - * If a document is supplied, then it will be used to create the resulting elements. - * If the document does not have a Document Element set, then the resulting - * element will be set as the Document Element. If no document is supplied, then - * a new document will be created and bound to the lifetime of the root object being - * marshalled, unless an existing DOM can be reused without creating a new document. - * - * @param document the DOM document the marshalled element will be placed in, or NULL - * @param sigs ordered array of signatures to create after marshalling is complete - * @return the DOM element representing this XMLObject - * - * @throws MarshallingException thrown if there is a problem marshalling the given object - * @throws SignatureException thrown if a problem occurs during signature creation - */ - virtual DOMElement* marshall( - DOMDocument* document=NULL -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs=NULL -#endif - ) const=0; - - /** - * Marshalls the XMLObject and appends it as a child of the given parent element. - * - * NOTE: The given Element must be within a DOM tree rooted in - * the Document owning the given Element. - * - * @param parentElement the parent element to append the resulting DOM tree - * @param sigs ordered array of signatures to create after marshalling is complete - * @return the marshalled element tree - - * @throws MarshallingException thrown if the given XMLObject can not be marshalled. - * @throws SignatureException thrown if a problem occurs during signature creation - */ - virtual DOMElement* marshall( - DOMElement* parentElement -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs=NULL -#endif - ) const=0; - - /** - * Unmarshalls the given W3C DOM element into the XMLObject. - * The root of a given XML construct should be unmarshalled with the bindDocument parameter - * set to true. - * - * @param element the DOM element to unmarshall - * @param bindDocument true iff the resulting XMLObject should take ownership of the DOM's Document - * - * @return the unmarshalled XMLObject - * - * @throws UnmarshallingException thrown if an error occurs unmarshalling the DOM element into the XMLObject - */ - virtual XMLObject* unmarshall(DOMElement* element, bool bindDocument=false)=0; - - protected: - XMLObject() {} - private: - XMLObject& operator=(const XMLObject& src); - }; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -}; - -#endif /* __xmltooling_xmlobj_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 XMLObject.h + * + * Abstract interface to objects that can be manipulated in and out of XML form. + */ + +#ifndef __xmltooling_xmlobj_h__ +#define __xmltooling_xmlobj_h__ + +#include +#include +#include +#include +#include +#include + +using namespace xercesc; + +#ifndef XMLTOOLING_NO_XMLSEC +namespace xmlsignature { + class XMLTOOL_API Signature; +}; +#endif + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * Object that represents an XML Element that has been unmarshalled into this C++ object. + */ + class XMLTOOL_API XMLObject + { + public: + virtual ~XMLObject() {} + + /** + * Creates a copy of the object, along with all of its children. + * + * The new object tree will be completely distinct and independent of + * the original in all respects. + */ + virtual XMLObject* clone() const=0; + + /** + * Specialized function for detaching a child object from its parent + * while disposing of the parent. + * + * This is not a generic way of detaching any child object, but only of + * pruning a single child from the root of an XMLObject tree. If the + * detached XMLObject's parent is itself a child, an exception will be + * thrown. It's mainly useful for turning a child into the new root of + * the tree without having to clone the child. + */ + virtual void detach()=0; + + /** + * Gets the QName for this element. This QName MUST + * contain the namespace URI, namespace prefix, and local element name. + * + * @return constant reference to the QName for this object + */ + virtual const QName& getElementQName() const=0; + + /** + * Gets the namespaces that are scoped to this element. + * + * The caller MUST NOT modify the set returned, but may use any + * non-modifying operations or algorithms on it. Iterators will + * remain valid unless the set member referenced is removed using + * the removeNamespace method. + * + * @return the namespaces that are scoped to this element + */ + virtual const std::set& getNamespaces() const=0; + + /** + * Adds a namespace to the ones already scoped to this element + * + * @param ns the namespace to add + */ + virtual void addNamespace(const Namespace& ns) const=0; + + /** + * Removes a namespace from this element + * + * @param ns the namespace to remove + */ + virtual void removeNamespace(const Namespace& ns)=0; + + /** + * Gets the XML schema type of this element. This translates to contents the xsi:type + * attribute for the element. + * + * @return XML schema type of this element + */ + virtual const QName* getSchemaType() const=0; + + /** + * Gets the value of the ID attribute set on this object, if any. + * + * @return an ID value or NULL + */ + virtual const XMLCh* getXMLID() const=0; + + /** + * Checks to see if this object has a parent. + * + * @return true if the object has a parent, false if not + */ + virtual bool hasParent() const=0; + + /** + * Gets the parent of this element or null if there is no parent. + * + * @return the parent of this element or null + */ + virtual XMLObject* getParent() const=0; + + /** + * Sets the parent of this element. + * + * @param parent the parent of this element + */ + virtual void setParent(XMLObject* parent)=0; + + /** + * Checks if this XMLObject has children. + * + * @return true if this XMLObject has children, false if not + */ + virtual bool hasChildren() const=0; + + /** + * Returns an unmodifiable list of child objects in the order that they + * should appear in the serialized representation. + * + * The validity of the returned list is not maintained if any non-const + * operations are performed on the parent object. + * + * @return the list of children + */ + virtual const std::list& getOrderedChildren() const=0; + + /** + * Used by a child's detach method to isolate the child from + * this parent object in preparation for destroying the parent + * (this object). + * + * @param child the child object to remove + */ + virtual void removeChild(XMLObject* child)=0; + + /** + * Returns the text content at the specified position relative to + * any child elements. A zero represents leading text, 1 comes after + * the first child, and so forth. + * + * @param position the relative child element position of the text + * @return the designated text value + */ + virtual const XMLCh* getTextContent(unsigned int position=0) const=0; + + /** + * Sets (or clears) text content relative to a child element's position. + * + * @param value value to set, or NULL to clear + * @param position position relative to child element + */ + virtual void setTextContent(const XMLCh* value, unsigned int position=0)=0; + + /** + * Gets the DOM representation of this XMLObject, if one exists. + * + * @return the DOM representation of this XMLObject + */ + virtual DOMElement* getDOM() const=0; + + /** + * Sets the DOM representation of this XMLObject. + * + * @param dom DOM representation of this XMLObject + * @param bindDocument true if the object should take ownership of the associated Document + */ + virtual void setDOM(DOMElement* dom, bool bindDocument=false) const=0; + + /** + * Assigns ownership of a DOM document to the XMLObject. + * This binds the lifetime of the document to the lifetime of the object. + * + * @param doc DOM document bound to this object + */ + virtual void setDocument(DOMDocument* doc) const=0; + + /** + * Releases the DOM representation of this XMLObject, if there is one. + */ + virtual void releaseDOM() const=0; + + /** + * Releases the DOM representation of this XMLObject's parent. + * + * @param propagateRelease true if all ancestors of this element should release their DOM + */ + virtual void releaseParentDOM(bool propagateRelease=true) const=0; + + /** + * Releases the DOM representation of this XMLObject's children. + * + * @param propagateRelease true if all descendants of this element should release their DOM + */ + virtual void releaseChildrenDOM(bool propagateRelease=true) const=0; + + /** + * A convenience method that is equal to calling releaseDOM() then releaseParentDOM(true). + */ + void releaseThisandParentDOM() const { + if (getDOM()) { + releaseDOM(); + releaseParentDOM(true); + } + } + + /** + * A convenience method that is equal to calling releaseChildrenDOM(true) then releaseDOM(). + */ + void releaseThisAndChildrenDOM() const { + if (getDOM()) { + releaseChildrenDOM(true); + releaseDOM(); + } + } + + /** + * Marshalls the XMLObject, and its children, into a DOM element. + * If a document is supplied, then it will be used to create the resulting elements. + * If the document does not have a Document Element set, then the resulting + * element will be set as the Document Element. If no document is supplied, then + * a new document will be created and bound to the lifetime of the root object being + * marshalled, unless an existing DOM can be reused without creating a new document. + * + * @param document the DOM document the marshalled element will be placed in, or NULL + * @param sigs ordered array of signatures to create after marshalling is complete + * @return the DOM element representing this XMLObject + * + * @throws MarshallingException thrown if there is a problem marshalling the given object + * @throws SignatureException thrown if a problem occurs during signature creation + */ + virtual DOMElement* marshall( + DOMDocument* document=NULL +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const=0; + + /** + * Marshalls the XMLObject and appends it as a child of the given parent element. + * + * NOTE: The given Element must be within a DOM tree rooted in + * the Document owning the given Element. + * + * @param parentElement the parent element to append the resulting DOM tree + * @param sigs ordered array of signatures to create after marshalling is complete + * @return the marshalled element tree + + * @throws MarshallingException thrown if the given XMLObject can not be marshalled. + * @throws SignatureException thrown if a problem occurs during signature creation + */ + virtual DOMElement* marshall( + DOMElement* parentElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const=0; + + /** + * Unmarshalls the given W3C DOM element into the XMLObject. + * The root of a given XML construct should be unmarshalled with the bindDocument parameter + * set to true. + * + * @param element the DOM element to unmarshall + * @param bindDocument true iff the resulting XMLObject should take ownership of the DOM's Document + * + * @return the unmarshalled XMLObject + * + * @throws UnmarshallingException thrown if an error occurs unmarshalling the DOM element into the XMLObject + */ + virtual XMLObject* unmarshall(DOMElement* element, bool bindDocument=false)=0; + + protected: + XMLObject() {} + private: + XMLObject& operator=(const XMLObject& src); + }; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +}; + +#endif /* __xmltooling_xmlobj_h__ */ diff --git a/xmltooling/XMLObjectBuilder.cpp b/xmltooling/XMLObjectBuilder.cpp index 33c4225..38d739b 100644 --- a/xmltooling/XMLObjectBuilder.cpp +++ b/xmltooling/XMLObjectBuilder.cpp @@ -1,73 +1,73 @@ -/* - * 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. - */ - -/** - * XMLObjectBuilder.cpp - * - * Factory interface for XMLObjects - */ - -#include "internal.h" -#include "XMLObjectBuilder.h" -#include "util/NDC.h" -#include "util/XMLHelper.h" - -#include - -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -map XMLObjectBuilder::m_map; -XMLObjectBuilder* XMLObjectBuilder::m_default=NULL; - -const XMLObjectBuilder* XMLObjectBuilder::getBuilder(const DOMElement* domElement) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("getBuilder"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".XMLObjectBuilder"); - - auto_ptr schemaType(XMLHelper::getXSIType(domElement)); - const XMLObjectBuilder* xmlObjectBuilder = schemaType.get() ? getBuilder(*(schemaType.get())) : NULL; - if (xmlObjectBuilder) { - if (log.isDebugEnabled()) { - log.debug("located XMLObjectBuilder for schema type: %s", schemaType->toString().c_str()); - } - return xmlObjectBuilder; - } - - auto_ptr elementName(XMLHelper::getNodeQName(domElement)); - xmlObjectBuilder = getBuilder(*(elementName.get())); - if (xmlObjectBuilder) { - if (log.isDebugEnabled()) { - log.debug("located XMLObjectBuilder for element name: %s", elementName->toString().c_str()); - } - return xmlObjectBuilder; - } - - if (log.isDebugEnabled()) { - log.debug("no XMLObjectBuilder registered for element (%s), returning default", elementName->toString().c_str()); - } - return m_default; -} - -void XMLObjectBuilder::destroyBuilders() -{ - for_each(m_map.begin(),m_map.end(),cleanup_pair()); - m_map.clear(); - deregisterDefaultBuilder(); -} +/* + * 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. + */ + +/** + * XMLObjectBuilder.cpp + * + * Factory interface for XMLObjects + */ + +#include "internal.h" +#include "XMLObjectBuilder.h" +#include "util/NDC.h" +#include "util/XMLHelper.h" + +#include + +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +map XMLObjectBuilder::m_map; +XMLObjectBuilder* XMLObjectBuilder::m_default=NULL; + +const XMLObjectBuilder* XMLObjectBuilder::getBuilder(const DOMElement* domElement) +{ +#ifdef _DEBUG + xmltooling::NDC ndc("getBuilder"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".XMLObjectBuilder"); + + auto_ptr schemaType(XMLHelper::getXSIType(domElement)); + const XMLObjectBuilder* xmlObjectBuilder = schemaType.get() ? getBuilder(*(schemaType.get())) : NULL; + if (xmlObjectBuilder) { + if (log.isDebugEnabled()) { + log.debug("located XMLObjectBuilder for schema type: %s", schemaType->toString().c_str()); + } + return xmlObjectBuilder; + } + + auto_ptr elementName(XMLHelper::getNodeQName(domElement)); + xmlObjectBuilder = getBuilder(*(elementName.get())); + if (xmlObjectBuilder) { + if (log.isDebugEnabled()) { + log.debug("located XMLObjectBuilder for element name: %s", elementName->toString().c_str()); + } + return xmlObjectBuilder; + } + + if (log.isDebugEnabled()) { + log.debug("no XMLObjectBuilder registered for element (%s), returning default", elementName->toString().c_str()); + } + return m_default; +} + +void XMLObjectBuilder::destroyBuilders() +{ + for_each(m_map.begin(),m_map.end(),cleanup_pair()); + m_map.clear(); + deregisterDefaultBuilder(); +} diff --git a/xmltooling/XMLToolingConfig.h b/xmltooling/XMLToolingConfig.h index 737fe31..f29f706 100644 --- a/xmltooling/XMLToolingConfig.h +++ b/xmltooling/XMLToolingConfig.h @@ -1,201 +1,201 @@ -/* - * 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 XMLToolingConfig.h - * - * Library configuration - */ - -#ifndef __xmltooling_config_h__ -#define __xmltooling_config_h__ - -#include -#include -#include - -#ifndef XMLTOOLING_NO_XMLSEC -namespace xmlsignature { - class XMLTOOL_API CredentialResolver; - class XMLTOOL_API KeyResolver; -}; -#endif - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4251 ) -#endif - -namespace xmltooling { - - class XMLTOOL_API ReplayCache; - class XMLTOOL_API StorageService; - class XMLTOOL_API TrustEngine; - class XMLTOOL_API XSECCryptoX509CRL; - - /** - * Singleton object that manages library startup/shutdown.configuration. - * - * A locking interface is supplied as a convenience for code that wants to - * obtain a global system lock, but the actual configuration itself is not - * synchronized. - */ - class XMLTOOL_API XMLToolingConfig : public Lockable - { - MAKE_NONCOPYABLE(XMLToolingConfig); - protected: - XMLToolingConfig() : m_replayCache(NULL), clock_skew_secs(180) {} - - /** Global ReplayCache instance. */ - ReplayCache* m_replayCache; - public: - virtual ~XMLToolingConfig() {} - - /** - * Returns the global configuration object for the library. - * - * @return reference to the global library configuration object - */ - static XMLToolingConfig& getConfig(); - - /** - * Initializes library - * - * Each process using the library MUST call this function exactly once - * before using any library classes except for the LogConfig method. - * - * @return true iff initialization was successful - */ - virtual bool init()=0; - - /** - * Shuts down library - * - * Each process using the library SHOULD call this function exactly once - * before terminating itself - */ - virtual void term()=0; - - /** - * Loads a shared/dynamic library extension. - * - * Extension libraries are managed using a pair of "C" linkage functions:
- * extern "C" int xmltooling_extension_init(void* context);
- * extern "C" void xmltooling_extension_term(); - * - * This method is internally synchronized. - * - * @param path pathname of shared library to load into process - * @param context arbitrary data to pass to library initialization hook - * @return true iff library was loaded successfully - */ - virtual bool load_library(const char* path, void* context=NULL)=0; - - /** - * Configure logging system. - * - * May be called first, before initializing the library. Other calls to it - * must be externally synchronized. - * - * @param config either a logging configuration file, or a level from the set - * (DEBUG, INFO, NOTICE, WARN, ERROR, CRIT, ALERT, FATAL, EMERG) - * @return true iff configuration was successful - */ - virtual bool log_config(const char* config=NULL)=0; - - /** - * Obtains a non-validating parser pool. - * Library must be initialized first. - * - * @return reference to a non-validating parser pool. - */ - virtual ParserPool& getParser() const=0; - - /** - * Obtains a validating parser pool. - * Library must be initialized first. Schema/catalog registration must be - * externally synchronized. - * - * @return reference to a validating parser pool. - */ - virtual ParserPool& getValidatingParser() const=0; - - /** - * Sets the global ReplayCache instance. - * This method must be externally synchronized with any code that uses the object. - * Any previously set object is destroyed. - * - * @param replayCache new ReplayCache instance to store - */ - void setReplayCache(ReplayCache* replayCache); - - /** - * Returns the global ReplayCache instance. - * - * @return global ReplayCache or NULL - */ - ReplayCache* getReplayCache() const { - return m_replayCache; - } - - /** - * List of catalog files to load into validating parser pool at initialization time. - * Like other path settings, the separator depends on the platform - * (semicolon on Windows, colon otherwise). - */ - std::string catalog_path; - - /** - * Adjusts any clock comparisons to be more liberal/permissive by the - * indicated number of seconds. - */ - unsigned int clock_skew_secs; - -#ifndef XMLTOOLING_NO_XMLSEC - /** - * Returns an X.509 CRL implementation object. - */ - virtual XSECCryptoX509CRL* X509CRL() const=0; - - /** - * Manages factories for KeyResolver plugins. - */ - PluginManager KeyResolverManager; - - /** - * Manages factories for CredentialResolver plugins. - */ - PluginManager CredentialResolverManager; - - /** - * Manages factories for TrustEngine plugins. - */ - PluginManager TrustEngineManager; -#endif - - /** - * Manages factories for StorageService plugins. - */ - PluginManager StorageServiceManager; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_config_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 XMLToolingConfig.h + * + * Library configuration + */ + +#ifndef __xmltooling_config_h__ +#define __xmltooling_config_h__ + +#include +#include +#include + +#ifndef XMLTOOLING_NO_XMLSEC +namespace xmlsignature { + class XMLTOOL_API CredentialResolver; + class XMLTOOL_API KeyResolver; +}; +#endif + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4251 ) +#endif + +namespace xmltooling { + + class XMLTOOL_API ReplayCache; + class XMLTOOL_API StorageService; + class XMLTOOL_API TrustEngine; + class XMLTOOL_API XSECCryptoX509CRL; + + /** + * Singleton object that manages library startup/shutdown.configuration. + * + * A locking interface is supplied as a convenience for code that wants to + * obtain a global system lock, but the actual configuration itself is not + * synchronized. + */ + class XMLTOOL_API XMLToolingConfig : public Lockable + { + MAKE_NONCOPYABLE(XMLToolingConfig); + protected: + XMLToolingConfig() : m_replayCache(NULL), clock_skew_secs(180) {} + + /** Global ReplayCache instance. */ + ReplayCache* m_replayCache; + public: + virtual ~XMLToolingConfig() {} + + /** + * Returns the global configuration object for the library. + * + * @return reference to the global library configuration object + */ + static XMLToolingConfig& getConfig(); + + /** + * Initializes library + * + * Each process using the library MUST call this function exactly once + * before using any library classes except for the LogConfig method. + * + * @return true iff initialization was successful + */ + virtual bool init()=0; + + /** + * Shuts down library + * + * Each process using the library SHOULD call this function exactly once + * before terminating itself + */ + virtual void term()=0; + + /** + * Loads a shared/dynamic library extension. + * + * Extension libraries are managed using a pair of "C" linkage functions:
+ * extern "C" int xmltooling_extension_init(void* context);
+ * extern "C" void xmltooling_extension_term(); + * + * This method is internally synchronized. + * + * @param path pathname of shared library to load into process + * @param context arbitrary data to pass to library initialization hook + * @return true iff library was loaded successfully + */ + virtual bool load_library(const char* path, void* context=NULL)=0; + + /** + * Configure logging system. + * + * May be called first, before initializing the library. Other calls to it + * must be externally synchronized. + * + * @param config either a logging configuration file, or a level from the set + * (DEBUG, INFO, NOTICE, WARN, ERROR, CRIT, ALERT, FATAL, EMERG) + * @return true iff configuration was successful + */ + virtual bool log_config(const char* config=NULL)=0; + + /** + * Obtains a non-validating parser pool. + * Library must be initialized first. + * + * @return reference to a non-validating parser pool. + */ + virtual ParserPool& getParser() const=0; + + /** + * Obtains a validating parser pool. + * Library must be initialized first. Schema/catalog registration must be + * externally synchronized. + * + * @return reference to a validating parser pool. + */ + virtual ParserPool& getValidatingParser() const=0; + + /** + * Sets the global ReplayCache instance. + * This method must be externally synchronized with any code that uses the object. + * Any previously set object is destroyed. + * + * @param replayCache new ReplayCache instance to store + */ + void setReplayCache(ReplayCache* replayCache); + + /** + * Returns the global ReplayCache instance. + * + * @return global ReplayCache or NULL + */ + ReplayCache* getReplayCache() const { + return m_replayCache; + } + + /** + * List of catalog files to load into validating parser pool at initialization time. + * Like other path settings, the separator depends on the platform + * (semicolon on Windows, colon otherwise). + */ + std::string catalog_path; + + /** + * Adjusts any clock comparisons to be more liberal/permissive by the + * indicated number of seconds. + */ + unsigned int clock_skew_secs; + +#ifndef XMLTOOLING_NO_XMLSEC + /** + * Returns an X.509 CRL implementation object. + */ + virtual XSECCryptoX509CRL* X509CRL() const=0; + + /** + * Manages factories for KeyResolver plugins. + */ + PluginManager KeyResolverManager; + + /** + * Manages factories for CredentialResolver plugins. + */ + PluginManager CredentialResolverManager; + + /** + * Manages factories for TrustEngine plugins. + */ + PluginManager TrustEngineManager; +#endif + + /** + * Manages factories for StorageService plugins. + */ + PluginManager StorageServiceManager; + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_config_h__ */ diff --git a/xmltooling/config_pub_win32.h b/xmltooling/config_pub_win32.h index a121d61..50af9d3 100644 --- a/xmltooling/config_pub_win32.h +++ b/xmltooling/config_pub_win32.h @@ -1,6 +1,6 @@ -/* Define to 1 if you have an STL implementation that supports useful string - specialization. */ -#define HAVE_GOOD_STL 1 - -/* Define to 1 to disable XML-Security-dependent features. */ -/* #undef XMLTOOLING_NO_XMLSEC */ +/* Define to 1 if you have an STL implementation that supports useful string + specialization. */ +#define HAVE_GOOD_STL 1 + +/* Define to 1 to disable XML-Security-dependent features. */ +/* #undef XMLTOOLING_NO_XMLSEC */ diff --git a/xmltooling/encryption/EncryptedKeyResolver.h b/xmltooling/encryption/EncryptedKeyResolver.h index 01dcf85..39a9cb0 100644 --- a/xmltooling/encryption/EncryptedKeyResolver.h +++ b/xmltooling/encryption/EncryptedKeyResolver.h @@ -1,49 +1,49 @@ -/* - * 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 EncryptedKeyResolver.h - * - * Resolves encrypted keys based on EncryptedData information or other external factors. - */ - -#if !defined(__xmltooling_enckeyres_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_enckeyres_h__ - -#include -#include - -namespace xmlencryption { - - /** - * An API for resolving encrypted decryption keys. - */ - class XMLTOOL_API EncryptedKeyResolver : public xmlsignature::KeyResolver { - public: - virtual ~EncryptedKeyResolver() {} - - /** - * Returns an encrypted key based on the supplied KeyInfo information. - * - * @param encryptedData an encrypted object - * @return the resolved EncryptedKey object - */ - virtual EncryptedKey* resolveKey(EncryptedData* encryptedData)=0; - }; - -}; - -#endif /* __xmltooling_enckeyres_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 EncryptedKeyResolver.h + * + * Resolves encrypted keys based on EncryptedData information or other external factors. + */ + +#if !defined(__xmltooling_enckeyres_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_enckeyres_h__ + +#include +#include + +namespace xmlencryption { + + /** + * An API for resolving encrypted decryption keys. + */ + class XMLTOOL_API EncryptedKeyResolver : public xmlsignature::KeyResolver { + public: + virtual ~EncryptedKeyResolver() {} + + /** + * Returns an encrypted key based on the supplied KeyInfo information. + * + * @param encryptedData an encrypted object + * @return the resolved EncryptedKey object + */ + virtual EncryptedKey* resolveKey(EncryptedData* encryptedData)=0; + }; + +}; + +#endif /* __xmltooling_enckeyres_h__ */ diff --git a/xmltooling/impl/MemoryStorageService.cpp b/xmltooling/impl/MemoryStorageService.cpp index 505eea8..a7e8768 100644 --- a/xmltooling/impl/MemoryStorageService.cpp +++ b/xmltooling/impl/MemoryStorageService.cpp @@ -1,325 +1,325 @@ -/* - * Copyright 2001-2005 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. - */ - -/** - * MemoryStorageService.cpp - * - * In-memory "persistent" storage, suitable for simple applications. - */ - -#include "internal.h" -#include "util/NDC.h" -#include "util/StorageService.h" -#include "util/Threads.h" -#include "util/XMLHelper.h" - -#include -#include - -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -namespace xmltooling { - class XMLTOOL_DLLLOCAL MemoryStorageService : public StorageService - { - public: - MemoryStorageService(const DOMElement* e); - virtual ~MemoryStorageService(); - - void createString(const char* context, const char* key, const char* value, time_t expiration); - bool readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL); - bool updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0); - bool deleteString(const char* context, const char* key); - - void createText(const char* context, const char* key, const char* value, time_t expiration) { - return createString(context, key, value, expiration); - } - bool readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL) { - return readString(context, key, pvalue, pexpiration); - } - bool updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0) { - return updateString(context, key, value, expiration); - } - bool deleteText(const char* context, const char* key) { - return deleteString(context, key); - } - - void reap(const char* context); - void deleteContext(const char* context) { - Lock wrapper(contextLock); - m_contextMap.erase(context); - } - - private: - void cleanup(); - - struct XMLTOOL_DLLLOCAL Record { - Record() : expiration(0) {} - Record(string s, time_t t) : data(s), expiration(t) {} - string data; - time_t expiration; - }; - - struct XMLTOOL_DLLLOCAL Context { - Context() : m_lock(RWLock::create()) {} - Context(const Context& src) { - m_dataMap = src.m_dataMap; - m_expMap = src.m_expMap; - m_lock = RWLock::create(); - } - ~Context() { delete m_lock; } - map m_dataMap; - multimap m_expMap; - RWLock* m_lock; - unsigned long reap(); - }; - - Context& getContext(const char* context) { - Lock wrapper(contextLock); - return m_contextMap[context]; - } - - map m_contextMap; - Mutex* contextLock; - CondWait* shutdown_wait; - Thread* cleanup_thread; - static void* cleanup_fn(void*); - bool shutdown; - int m_cleanupInterval; - Category& m_log; - }; - - StorageService* XMLTOOL_DLLLOCAL MemoryStorageServiceFactory(const DOMElement* const & e) - { - return new MemoryStorageService(e); - } - -}; - -static const XMLCh cleanupInterval[] = UNICODE_LITERAL_15(c,l,e,a,n,u,p,I,n,t,e,r,v,a,l); - -MemoryStorageService::MemoryStorageService(const DOMElement* e) - : contextLock(NULL), shutdown_wait(NULL), cleanup_thread(NULL), shutdown(false), m_cleanupInterval(0), - m_log(Category::getInstance(XMLTOOLING_LOGCAT".StorageService")) -{ - const XMLCh* tag=e ? e->getAttributeNS(NULL,cleanupInterval) : NULL; - if (tag && *tag) { - m_cleanupInterval = XMLString::parseInt(tag); - } - if (!m_cleanupInterval) - m_cleanupInterval=300; - - contextLock = Mutex::create(); - shutdown_wait = CondWait::create(); - cleanup_thread = Thread::create(&cleanup_fn, (void*)this); -} - -MemoryStorageService::~MemoryStorageService() -{ - // Shut down the cleanup thread and let it know... - shutdown = true; - shutdown_wait->signal(); - cleanup_thread->join(NULL); - - delete shutdown_wait; - delete contextLock; -} - -void* MemoryStorageService::cleanup_fn(void* cache_p) -{ - MemoryStorageService* cache = reinterpret_cast(cache_p); - -#ifndef WIN32 - // First, let's block all signals - Thread::mask_all_signals(); -#endif - - // Now run the cleanup process. - cache->cleanup(); - return NULL; -} - -void MemoryStorageService::cleanup() -{ -#ifdef _DEBUG - NDC ndc("cleanup"); -#endif - - - Mutex* mutex = Mutex::create(); - mutex->lock(); - - m_log.info("cleanup thread started...running every %d seconds", m_cleanupInterval); - - while (!shutdown) { - shutdown_wait->timedwait(mutex, m_cleanupInterval); - if (shutdown) - break; - - unsigned long count=0; - Lock wrapper(contextLock); - for (map::iterator i=m_contextMap.begin(); i!=m_contextMap.end(); ++i) - count += i->second.reap(); - - if (count) - m_log.info("purged %d record(s) from storage", count); - } - - m_log.info("cleanup thread finished"); - - mutex->unlock(); - delete mutex; - Thread::exit(NULL); -} - -void MemoryStorageService::reap(const char* context) -{ - getContext(context).reap(); -} - -unsigned long MemoryStorageService::Context::reap() -{ - // Lock the "database". - m_lock->wrlock(); - SharedLock wrapper(m_lock, false); - - // Garbage collect any expired entries. - unsigned long count=0; - multimap::iterator stop=m_expMap.upper_bound(time(NULL)); - for (multimap::iterator i=m_expMap.begin(); i!=stop; m_expMap.erase(i++)) { - m_dataMap.erase(i->second); - ++count; - } - - return count; -} - -void MemoryStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) -{ - Context& ctx = getContext(context); - - // Lock the maps. - ctx.m_lock->wrlock(); - SharedLock wrapper(ctx.m_lock, false); - - // Check for a duplicate. - map::iterator i=ctx.m_dataMap.find(key); - if (i!=ctx.m_dataMap.end()) { - // Not yet expired? - if (time(NULL) < i->second.expiration) - throw IOException("attempted to insert a record with duplicate key ($1)", params(1,key)); - // It's dead, so we can just remove it now and create the new record. - // Now find the reversed index of expiration to key, so we can clear it. - pair::iterator,multimap::iterator> range = - ctx.m_expMap.equal_range(i->second.expiration); - for (; range.first != range.second; ++range.first) { - if (range.first->second == i->first) { - ctx.m_expMap.erase(range.first); - break; - } - } - // And finally delete the record itself. - ctx.m_dataMap.erase(i); - } - - ctx.m_dataMap[key]=Record(value,expiration); - ctx.m_expMap.insert(multimap::value_type(expiration,key)); - - m_log.debug("inserted record (%s) in context (%s)", key, context); -} - -bool MemoryStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration) -{ - Context& ctx = getContext(context); - - SharedLock wrapper(ctx.m_lock); - map::iterator i=ctx.m_dataMap.find(key); - if (i==ctx.m_dataMap.end()) - return false; - else if (time(NULL) >= i->second.expiration) - return false; - if (pvalue) - *pvalue = i->second.data; - if (pexpiration) - *pexpiration = i->second.expiration; - return true; -} - -bool MemoryStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration) -{ - Context& ctx = getContext(context); - - // Lock the maps. - ctx.m_lock->wrlock(); - SharedLock wrapper(ctx.m_lock, false); - - map::iterator i=ctx.m_dataMap.find(key); - if (i==ctx.m_dataMap.end()) - return false; - else if (time(NULL) >= i->second.expiration) - return false; - - if (value) - i->second.data = value; - - if (expiration && expiration != i->second.expiration) { - // Update secondary map. - pair::iterator,multimap::iterator> range = - ctx.m_expMap.equal_range(i->second.expiration); - for (; range.first != range.second; ++range.first) { - if (range.first->second == i->first) { - ctx.m_expMap.erase(range.first); - break; - } - } - i->second.expiration = expiration; - ctx.m_expMap.insert(multimap::value_type(expiration,key)); - } - - m_log.debug("updated record (%s) in context (%s)", key, context); - return true; -} - -bool MemoryStorageService::deleteString(const char* context, const char* key) -{ - Context& ctx = getContext(context); - - // Lock the maps. - ctx.m_lock->wrlock(); - SharedLock wrapper(ctx.m_lock, false); - - // Find the record. - map::iterator i=ctx.m_dataMap.find(key); - if (i!=ctx.m_dataMap.end()) { - // Now find the reversed index of expiration to key, so we can clear it. - pair::iterator,multimap::iterator> range = - ctx.m_expMap.equal_range(i->second.expiration); - for (; range.first != range.second; ++range.first) { - if (range.first->second == i->first) { - ctx.m_expMap.erase(range.first); - break; - } - } - // And finally delete the record itself. - ctx.m_dataMap.erase(i); - m_log.debug("deleted record (%s) in context (%s)", key, context); - return true; - } - - m_log.debug("deleting record (%s) in context (%s)....not found", key, context); - return false; -} +/* + * Copyright 2001-2005 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. + */ + +/** + * MemoryStorageService.cpp + * + * In-memory "persistent" storage, suitable for simple applications. + */ + +#include "internal.h" +#include "util/NDC.h" +#include "util/StorageService.h" +#include "util/Threads.h" +#include "util/XMLHelper.h" + +#include +#include + +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +namespace xmltooling { + class XMLTOOL_DLLLOCAL MemoryStorageService : public StorageService + { + public: + MemoryStorageService(const DOMElement* e); + virtual ~MemoryStorageService(); + + void createString(const char* context, const char* key, const char* value, time_t expiration); + bool readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL); + bool updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0); + bool deleteString(const char* context, const char* key); + + void createText(const char* context, const char* key, const char* value, time_t expiration) { + return createString(context, key, value, expiration); + } + bool readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL) { + return readString(context, key, pvalue, pexpiration); + } + bool updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0) { + return updateString(context, key, value, expiration); + } + bool deleteText(const char* context, const char* key) { + return deleteString(context, key); + } + + void reap(const char* context); + void deleteContext(const char* context) { + Lock wrapper(contextLock); + m_contextMap.erase(context); + } + + private: + void cleanup(); + + struct XMLTOOL_DLLLOCAL Record { + Record() : expiration(0) {} + Record(string s, time_t t) : data(s), expiration(t) {} + string data; + time_t expiration; + }; + + struct XMLTOOL_DLLLOCAL Context { + Context() : m_lock(RWLock::create()) {} + Context(const Context& src) { + m_dataMap = src.m_dataMap; + m_expMap = src.m_expMap; + m_lock = RWLock::create(); + } + ~Context() { delete m_lock; } + map m_dataMap; + multimap m_expMap; + RWLock* m_lock; + unsigned long reap(); + }; + + Context& getContext(const char* context) { + Lock wrapper(contextLock); + return m_contextMap[context]; + } + + map m_contextMap; + Mutex* contextLock; + CondWait* shutdown_wait; + Thread* cleanup_thread; + static void* cleanup_fn(void*); + bool shutdown; + int m_cleanupInterval; + Category& m_log; + }; + + StorageService* XMLTOOL_DLLLOCAL MemoryStorageServiceFactory(const DOMElement* const & e) + { + return new MemoryStorageService(e); + } + +}; + +static const XMLCh cleanupInterval[] = UNICODE_LITERAL_15(c,l,e,a,n,u,p,I,n,t,e,r,v,a,l); + +MemoryStorageService::MemoryStorageService(const DOMElement* e) + : contextLock(NULL), shutdown_wait(NULL), cleanup_thread(NULL), shutdown(false), m_cleanupInterval(0), + m_log(Category::getInstance(XMLTOOLING_LOGCAT".StorageService")) +{ + const XMLCh* tag=e ? e->getAttributeNS(NULL,cleanupInterval) : NULL; + if (tag && *tag) { + m_cleanupInterval = XMLString::parseInt(tag); + } + if (!m_cleanupInterval) + m_cleanupInterval=300; + + contextLock = Mutex::create(); + shutdown_wait = CondWait::create(); + cleanup_thread = Thread::create(&cleanup_fn, (void*)this); +} + +MemoryStorageService::~MemoryStorageService() +{ + // Shut down the cleanup thread and let it know... + shutdown = true; + shutdown_wait->signal(); + cleanup_thread->join(NULL); + + delete shutdown_wait; + delete contextLock; +} + +void* MemoryStorageService::cleanup_fn(void* cache_p) +{ + MemoryStorageService* cache = reinterpret_cast(cache_p); + +#ifndef WIN32 + // First, let's block all signals + Thread::mask_all_signals(); +#endif + + // Now run the cleanup process. + cache->cleanup(); + return NULL; +} + +void MemoryStorageService::cleanup() +{ +#ifdef _DEBUG + NDC ndc("cleanup"); +#endif + + + Mutex* mutex = Mutex::create(); + mutex->lock(); + + m_log.info("cleanup thread started...running every %d seconds", m_cleanupInterval); + + while (!shutdown) { + shutdown_wait->timedwait(mutex, m_cleanupInterval); + if (shutdown) + break; + + unsigned long count=0; + Lock wrapper(contextLock); + for (map::iterator i=m_contextMap.begin(); i!=m_contextMap.end(); ++i) + count += i->second.reap(); + + if (count) + m_log.info("purged %d record(s) from storage", count); + } + + m_log.info("cleanup thread finished"); + + mutex->unlock(); + delete mutex; + Thread::exit(NULL); +} + +void MemoryStorageService::reap(const char* context) +{ + getContext(context).reap(); +} + +unsigned long MemoryStorageService::Context::reap() +{ + // Lock the "database". + m_lock->wrlock(); + SharedLock wrapper(m_lock, false); + + // Garbage collect any expired entries. + unsigned long count=0; + multimap::iterator stop=m_expMap.upper_bound(time(NULL)); + for (multimap::iterator i=m_expMap.begin(); i!=stop; m_expMap.erase(i++)) { + m_dataMap.erase(i->second); + ++count; + } + + return count; +} + +void MemoryStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) +{ + Context& ctx = getContext(context); + + // Lock the maps. + ctx.m_lock->wrlock(); + SharedLock wrapper(ctx.m_lock, false); + + // Check for a duplicate. + map::iterator i=ctx.m_dataMap.find(key); + if (i!=ctx.m_dataMap.end()) { + // Not yet expired? + if (time(NULL) < i->second.expiration) + throw IOException("attempted to insert a record with duplicate key ($1)", params(1,key)); + // It's dead, so we can just remove it now and create the new record. + // Now find the reversed index of expiration to key, so we can clear it. + pair::iterator,multimap::iterator> range = + ctx.m_expMap.equal_range(i->second.expiration); + for (; range.first != range.second; ++range.first) { + if (range.first->second == i->first) { + ctx.m_expMap.erase(range.first); + break; + } + } + // And finally delete the record itself. + ctx.m_dataMap.erase(i); + } + + ctx.m_dataMap[key]=Record(value,expiration); + ctx.m_expMap.insert(multimap::value_type(expiration,key)); + + m_log.debug("inserted record (%s) in context (%s)", key, context); +} + +bool MemoryStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration) +{ + Context& ctx = getContext(context); + + SharedLock wrapper(ctx.m_lock); + map::iterator i=ctx.m_dataMap.find(key); + if (i==ctx.m_dataMap.end()) + return false; + else if (time(NULL) >= i->second.expiration) + return false; + if (pvalue) + *pvalue = i->second.data; + if (pexpiration) + *pexpiration = i->second.expiration; + return true; +} + +bool MemoryStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration) +{ + Context& ctx = getContext(context); + + // Lock the maps. + ctx.m_lock->wrlock(); + SharedLock wrapper(ctx.m_lock, false); + + map::iterator i=ctx.m_dataMap.find(key); + if (i==ctx.m_dataMap.end()) + return false; + else if (time(NULL) >= i->second.expiration) + return false; + + if (value) + i->second.data = value; + + if (expiration && expiration != i->second.expiration) { + // Update secondary map. + pair::iterator,multimap::iterator> range = + ctx.m_expMap.equal_range(i->second.expiration); + for (; range.first != range.second; ++range.first) { + if (range.first->second == i->first) { + ctx.m_expMap.erase(range.first); + break; + } + } + i->second.expiration = expiration; + ctx.m_expMap.insert(multimap::value_type(expiration,key)); + } + + m_log.debug("updated record (%s) in context (%s)", key, context); + return true; +} + +bool MemoryStorageService::deleteString(const char* context, const char* key) +{ + Context& ctx = getContext(context); + + // Lock the maps. + ctx.m_lock->wrlock(); + SharedLock wrapper(ctx.m_lock, false); + + // Find the record. + map::iterator i=ctx.m_dataMap.find(key); + if (i!=ctx.m_dataMap.end()) { + // Now find the reversed index of expiration to key, so we can clear it. + pair::iterator,multimap::iterator> range = + ctx.m_expMap.equal_range(i->second.expiration); + for (; range.first != range.second; ++range.first) { + if (range.first->second == i->first) { + ctx.m_expMap.erase(range.first); + break; + } + } + // And finally delete the record itself. + ctx.m_dataMap.erase(i); + m_log.debug("deleted record (%s) in context (%s)", key, context); + return true; + } + + m_log.debug("deleting record (%s) in context (%s)....not found", key, context); + return false; +} diff --git a/xmltooling/impl/UnknownElement.cpp b/xmltooling/impl/UnknownElement.cpp index e8ea23e..00b234e 100644 --- a/xmltooling/impl/UnknownElement.cpp +++ b/xmltooling/impl/UnknownElement.cpp @@ -1,206 +1,206 @@ -/* -* 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. - */ - -/** - * UnknownElement.cpp - * - * Basic implementation suitable for use as default for unrecognized content - */ - -#include "internal.h" -#include "exceptions.h" -#include "impl/UnknownElement.h" -#include "util/NDC.h" -#include "util/XMLHelper.h" - -#include -#include -#include -#include - -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -void UnknownElementImpl::releaseDOM() const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("releaseDOM"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".UnknownElementImpl"); - log.debug("releasing DOM for unknown content, preserving current DOM in XML form"); - - // We're losing our DOM, so assuming we have one, we preserve it. - serialize(m_xml); - - // This takes care of the generic housekeeping now that we've preserved things. - AbstractDOMCachingXMLObject::releaseDOM(); -} - -XMLObject* UnknownElementImpl::clone() const -{ - UnknownElementImpl* ret=new UnknownElementImpl(); - - // If there's no XML locally, serialize this object into the new one. - // Otherwise just copy it over. - if (m_xml.empty()) - serialize(ret->m_xml); - else - ret->m_xml=m_xml; - - return ret; -} - -void UnknownElementImpl::serialize(string& s) const -{ - if (getDOM()) - XMLHelper::serialize(getDOM(),s); -} - -DOMElement* UnknownElementImpl::marshall( - DOMDocument* document -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs -#endif - ) const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("marshall"); -#endif - - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller"); - log.debug("marshalling unknown content"); - - DOMElement* cachedDOM=getDOM(); - if (cachedDOM) { - if (!document || document==cachedDOM->getOwnerDocument()) { - log.debug("XMLObject has a usable cached DOM, reusing it"); - if (document) - setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM); - releaseParentDOM(true); - return cachedDOM; - } - - // We have a DOM but it doesn't match the document we were given, so we import - // it into the new document. - cachedDOM=static_cast(document->importNode(cachedDOM, true)); - - // Recache the DOM. - setDocumentElement(document, cachedDOM); - log.debug("caching imported DOM for XMLObject"); - setDOM(cachedDOM, false); - releaseParentDOM(true); - return cachedDOM; - } - - // If we get here, we didn't have a usable DOM. - // We need to reparse the XML we saved off into a new DOM. - bool bindDocument=false; - MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"UnknownElementImpl"); - Wrapper4InputSource dsrc(&src,false); - log.debug("parsing XML back into DOM tree"); - DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc); - if (document) { - // The caller insists on using his own document, so we now have to import the thing - // into it. Then we're just dumping the one we built. - log.debug("reimporting new DOM into caller-supplied document"); - cachedDOM=static_cast(document->importNode(internalDoc->getDocumentElement(), true)); - internalDoc->release(); - } - else { - // We just bind the document we built to the object as the result. - cachedDOM=static_cast(internalDoc->getDocumentElement()); - document=internalDoc; - bindDocument=true; - } - - // Recache the DOM and clear the serialized copy. - setDocumentElement(document, cachedDOM); - log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not "); - setDOM(cachedDOM, bindDocument); - releaseParentDOM(true); - m_xml.erase(); - return cachedDOM; -} - - -DOMElement* UnknownElementImpl::marshall( - DOMElement* parentElement -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs -#endif - ) const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("marshall"); -#endif - - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller"); - log.debug("marshalling unknown content"); - - DOMElement* cachedDOM=getDOM(); - if (cachedDOM) { - if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { - log.debug("XMLObject has a usable cached DOM, reusing it"); - parentElement->appendChild(cachedDOM); - releaseParentDOM(true); - return cachedDOM; - } - - // We have a DOM but it doesn't match the document we were given, so we import - // it into the new document. - cachedDOM=static_cast(parentElement->getOwnerDocument()->importNode(cachedDOM, true)); - - // Recache the DOM. - parentElement->appendChild(cachedDOM); - log.debug("caching imported DOM for XMLObject"); - setDOM(cachedDOM, false); - releaseParentDOM(true); - return cachedDOM; - } - - // If we get here, we didn't have a usable DOM (and/or we flushed the one we had). - // We need to reparse the XML we saved off into a new DOM. - MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"UnknownElementImpl"); - Wrapper4InputSource dsrc(&src,false); - log.debug("parsing XML back into DOM tree"); - DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc); - - log.debug("reimporting new DOM into caller-supplied document"); - cachedDOM=static_cast(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(), true)); - internalDoc->release(); - - // Recache the DOM and clear the serialized copy. - parentElement->appendChild(cachedDOM); - log.debug("caching DOM for XMLObject"); - setDOM(cachedDOM, false); - releaseParentDOM(true); - m_xml.erase(); - return cachedDOM; -} - -XMLObject* UnknownElementImpl::unmarshall(DOMElement* element, bool bindDocument) -{ - setDOM(element, bindDocument); - return this; -} - -XMLObject* UnknownElementBuilder::buildObject( - const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType - ) const { - return new UnknownElementImpl(nsURI,localName,prefix); -} - +/* +* 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. + */ + +/** + * UnknownElement.cpp + * + * Basic implementation suitable for use as default for unrecognized content + */ + +#include "internal.h" +#include "exceptions.h" +#include "impl/UnknownElement.h" +#include "util/NDC.h" +#include "util/XMLHelper.h" + +#include +#include +#include +#include + +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +void UnknownElementImpl::releaseDOM() const +{ +#ifdef _DEBUG + xmltooling::NDC ndc("releaseDOM"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".UnknownElementImpl"); + log.debug("releasing DOM for unknown content, preserving current DOM in XML form"); + + // We're losing our DOM, so assuming we have one, we preserve it. + serialize(m_xml); + + // This takes care of the generic housekeeping now that we've preserved things. + AbstractDOMCachingXMLObject::releaseDOM(); +} + +XMLObject* UnknownElementImpl::clone() const +{ + UnknownElementImpl* ret=new UnknownElementImpl(); + + // If there's no XML locally, serialize this object into the new one. + // Otherwise just copy it over. + if (m_xml.empty()) + serialize(ret->m_xml); + else + ret->m_xml=m_xml; + + return ret; +} + +void UnknownElementImpl::serialize(string& s) const +{ + if (getDOM()) + XMLHelper::serialize(getDOM(),s); +} + +DOMElement* UnknownElementImpl::marshall( + DOMDocument* document +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs +#endif + ) const +{ +#ifdef _DEBUG + xmltooling::NDC ndc("marshall"); +#endif + + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller"); + log.debug("marshalling unknown content"); + + DOMElement* cachedDOM=getDOM(); + if (cachedDOM) { + if (!document || document==cachedDOM->getOwnerDocument()) { + log.debug("XMLObject has a usable cached DOM, reusing it"); + if (document) + setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM); + releaseParentDOM(true); + return cachedDOM; + } + + // We have a DOM but it doesn't match the document we were given, so we import + // it into the new document. + cachedDOM=static_cast(document->importNode(cachedDOM, true)); + + // Recache the DOM. + setDocumentElement(document, cachedDOM); + log.debug("caching imported DOM for XMLObject"); + setDOM(cachedDOM, false); + releaseParentDOM(true); + return cachedDOM; + } + + // If we get here, we didn't have a usable DOM. + // We need to reparse the XML we saved off into a new DOM. + bool bindDocument=false; + MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"UnknownElementImpl"); + Wrapper4InputSource dsrc(&src,false); + log.debug("parsing XML back into DOM tree"); + DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc); + if (document) { + // The caller insists on using his own document, so we now have to import the thing + // into it. Then we're just dumping the one we built. + log.debug("reimporting new DOM into caller-supplied document"); + cachedDOM=static_cast(document->importNode(internalDoc->getDocumentElement(), true)); + internalDoc->release(); + } + else { + // We just bind the document we built to the object as the result. + cachedDOM=static_cast(internalDoc->getDocumentElement()); + document=internalDoc; + bindDocument=true; + } + + // Recache the DOM and clear the serialized copy. + setDocumentElement(document, cachedDOM); + log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not "); + setDOM(cachedDOM, bindDocument); + releaseParentDOM(true); + m_xml.erase(); + return cachedDOM; +} + + +DOMElement* UnknownElementImpl::marshall( + DOMElement* parentElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs +#endif + ) const +{ +#ifdef _DEBUG + xmltooling::NDC ndc("marshall"); +#endif + + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Marshaller"); + log.debug("marshalling unknown content"); + + DOMElement* cachedDOM=getDOM(); + if (cachedDOM) { + if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { + log.debug("XMLObject has a usable cached DOM, reusing it"); + parentElement->appendChild(cachedDOM); + releaseParentDOM(true); + return cachedDOM; + } + + // We have a DOM but it doesn't match the document we were given, so we import + // it into the new document. + cachedDOM=static_cast(parentElement->getOwnerDocument()->importNode(cachedDOM, true)); + + // Recache the DOM. + parentElement->appendChild(cachedDOM); + log.debug("caching imported DOM for XMLObject"); + setDOM(cachedDOM, false); + releaseParentDOM(true); + return cachedDOM; + } + + // If we get here, we didn't have a usable DOM (and/or we flushed the one we had). + // We need to reparse the XML we saved off into a new DOM. + MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"UnknownElementImpl"); + Wrapper4InputSource dsrc(&src,false); + log.debug("parsing XML back into DOM tree"); + DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc); + + log.debug("reimporting new DOM into caller-supplied document"); + cachedDOM=static_cast(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(), true)); + internalDoc->release(); + + // Recache the DOM and clear the serialized copy. + parentElement->appendChild(cachedDOM); + log.debug("caching DOM for XMLObject"); + setDOM(cachedDOM, false); + releaseParentDOM(true); + m_xml.erase(); + return cachedDOM; +} + +XMLObject* UnknownElementImpl::unmarshall(DOMElement* element, bool bindDocument) +{ + setDOM(element, bindDocument); + return this; +} + +XMLObject* UnknownElementBuilder::buildObject( + const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType + ) const { + return new UnknownElementImpl(nsURI,localName,prefix); +} + diff --git a/xmltooling/impl/UnknownElement.h b/xmltooling/impl/UnknownElement.h index ce23b31..61129b2 100644 --- a/xmltooling/impl/UnknownElement.h +++ b/xmltooling/impl/UnknownElement.h @@ -1,108 +1,108 @@ -/* -* 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 xmltooling/impl/UnknownElement.h - * - * Basic implementation suitable for use as default for unrecognized content - */ - -#ifndef __xmltooling_unkelement_h__ -#define __xmltooling_unkelement_h__ - -#include -#include -#include -#include -#include - -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /// @cond off - class XMLTOOL_DLLLOCAL UnknownElementImpl : public AbstractSimpleElement, public AbstractDOMCachingXMLObject - { - public: - UnknownElementImpl(const XMLCh* namespaceURI=NULL, const XMLCh* elementLocalName=NULL, const XMLCh* namespacePrefix=NULL) - : AbstractXMLObject(namespaceURI, elementLocalName, namespacePrefix) {} - - void releaseDOM() const; - - XMLObject* clone() const; - - const XMLCh* getTextContent(unsigned int position=0) const { - throw XMLObjectException("Direct access to content is not permitted."); - } - - void setTextContent(const XMLCh*, unsigned int position=0) { - throw XMLObjectException("Direct access to content is not permitted."); - } - - DOMElement* marshall( - DOMDocument* document=NULL -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs=NULL -#endif - ) const; - - DOMElement* marshall( - DOMElement* parentElement -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs=NULL -#endif - ) const; - XMLObject* unmarshall(DOMElement* element, bool bindDocument=false); - - protected: - void setDocumentElement(DOMDocument* document, DOMElement* element) const { - DOMElement* documentRoot = document->getDocumentElement(); - if (documentRoot) - document->replaceChild(element, documentRoot); - else - document->appendChild(element); - } - - mutable std::string m_xml; - - void serialize(std::string& s) const; - }; - /// @endcond - - /** - * Builder for UnknownElementImpl objects. - * Use as the default builder when you want unknown DOM content treated as raw/ignored XML. - */ - class XMLTOOL_API UnknownElementBuilder : public XMLObjectBuilder - { - public: - XMLObject* buildObject( - const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix=NULL, const QName* schemaType=NULL - ) const; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_unkelement_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 xmltooling/impl/UnknownElement.h + * + * Basic implementation suitable for use as default for unrecognized content + */ + +#ifndef __xmltooling_unkelement_h__ +#define __xmltooling_unkelement_h__ + +#include +#include +#include +#include +#include + +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /// @cond off + class XMLTOOL_DLLLOCAL UnknownElementImpl : public AbstractSimpleElement, public AbstractDOMCachingXMLObject + { + public: + UnknownElementImpl(const XMLCh* namespaceURI=NULL, const XMLCh* elementLocalName=NULL, const XMLCh* namespacePrefix=NULL) + : AbstractXMLObject(namespaceURI, elementLocalName, namespacePrefix) {} + + void releaseDOM() const; + + XMLObject* clone() const; + + const XMLCh* getTextContent(unsigned int position=0) const { + throw XMLObjectException("Direct access to content is not permitted."); + } + + void setTextContent(const XMLCh*, unsigned int position=0) { + throw XMLObjectException("Direct access to content is not permitted."); + } + + DOMElement* marshall( + DOMDocument* document=NULL +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const; + + DOMElement* marshall( + DOMElement* parentElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const; + XMLObject* unmarshall(DOMElement* element, bool bindDocument=false); + + protected: + void setDocumentElement(DOMDocument* document, DOMElement* element) const { + DOMElement* documentRoot = document->getDocumentElement(); + if (documentRoot) + document->replaceChild(element, documentRoot); + else + document->appendChild(element); + } + + mutable std::string m_xml; + + void serialize(std::string& s) const; + }; + /// @endcond + + /** + * Builder for UnknownElementImpl objects. + * Use as the default builder when you want unknown DOM content treated as raw/ignored XML. + */ + class XMLTOOL_API UnknownElementBuilder : public XMLObjectBuilder + { + public: + XMLObject* buildObject( + const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix=NULL, const QName* schemaType=NULL + ) const; + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_unkelement_h__ */ diff --git a/xmltooling/io/AbstractXMLObjectMarshaller.cpp b/xmltooling/io/AbstractXMLObjectMarshaller.cpp index a33016c..d2cd392 100644 --- a/xmltooling/io/AbstractXMLObjectMarshaller.cpp +++ b/xmltooling/io/AbstractXMLObjectMarshaller.cpp @@ -1,309 +1,309 @@ -/* -* 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. - */ - -/** - * AbstractXMLObjectMarshaller.cpp - * - * A thread-safe abstract marshaller. - */ - -#include "internal.h" -#include "exceptions.h" -#include "io/AbstractXMLObjectMarshaller.h" -#ifndef XMLTOOLING_NO_XMLSEC - #include "signature/Signature.h" -#endif -#include "util/NDC.h" -#include "util/XMLConstants.h" -#include "util/XMLHelper.h" - -#include -#include -#include -#include - -#ifndef XMLTOOLING_NO_XMLSEC - using namespace xmlsignature; -#endif -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -#define XT_log (*static_cast(m_log)) - -DOMElement* AbstractXMLObjectMarshaller::marshall( - DOMDocument* document -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs -#endif - ) const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("marshall"); -#endif - - if (XT_log.isDebugEnabled()) { - XT_log.debug("starting to marshal %s", getElementQName().toString().c_str()); - } - - DOMElement* cachedDOM=getDOM(); - if (cachedDOM) { - if (!document || document==cachedDOM->getOwnerDocument()) { - XT_log.debug("XMLObject has a usable cached DOM, reusing it"); - if (document) - setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM); - releaseParentDOM(true); - return cachedDOM; - } - - // We have a DOM but it doesn't match the document we were given. This both sucks and blows. - // Without an adoptNode option to maintain the child pointers, we have to either import the - // DOM while somehow reassigning all the nested references (which amounts to a complete - // *unmarshall* operation), or we just release the existing DOM and hope that we can get - // it back. This depends on all objects being able to preserve their DOM at all costs. - releaseChildrenDOM(true); - releaseDOM(); - } - - // If we get here, we didn't have a usable DOM (and/or we released the one we had). - // We may need to create our own document. - bool bindDocument=false; - if (!document) { - document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument(); - bindDocument=true; - } - - XercesJanitor janitor(bindDocument ? document : NULL); - - XT_log.debug("creating root element to marshall"); - DOMElement* domElement = document->createElementNS( - getElementQName().getNamespaceURI(), getElementQName().getLocalPart() - ); - setDocumentElement(document, domElement); -#ifndef XMLTOOLING_NO_XMLSEC - marshallInto(domElement, sigs); -#else - marshallInto(domElement); -#endif - //Recache the DOM. - XT_log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not "); - setDOM(domElement, bindDocument); - janitor.release(); // safely transferred - releaseParentDOM(true); - - return domElement; -} - -DOMElement* AbstractXMLObjectMarshaller::marshall( - DOMElement* parentElement -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs -#endif - ) const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("marshall"); -#endif - - if (XT_log.isDebugEnabled()) { - XT_log.debug("starting to marshalling %s", getElementQName().toString().c_str()); - } - - DOMElement* cachedDOM=getDOM(); - if (cachedDOM) { - if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { - XT_log.debug("XMLObject has a usable cached DOM, reusing it"); - if (parentElement!=cachedDOM->getParentNode()) { - parentElement->appendChild(cachedDOM); - releaseParentDOM(true); - } - return cachedDOM; - } - - // We have a DOM but it doesn't match the document we were given. This both sucks and blows. - // Without an adoptNode option to maintain the child pointers, we have to either import the - // DOM while somehow reassigning all the nested references (which amounts to a complete - // *unmarshall* operation), or we just release the existing DOM and hope that we can get - // it back. This depends on all objects being able to preserve their DOM at all costs. - releaseChildrenDOM(true); - releaseDOM(); - } - - // If we get here, we didn't have a usable DOM (and/or we released the one we had). - XT_log.debug("creating root element to marshall"); - DOMElement* domElement = parentElement->getOwnerDocument()->createElementNS( - getElementQName().getNamespaceURI(), getElementQName().getLocalPart() - ); - parentElement->appendChild(domElement); -#ifndef XMLTOOLING_NO_XMLSEC - marshallInto(domElement, sigs); -#else - marshallInto(domElement); -#endif - - //Recache the DOM. - XT_log.debug("caching DOM for XMLObject"); - setDOM(domElement, false); - releaseParentDOM(true); - - return domElement; -} - -void AbstractXMLObjectMarshaller::marshallInto( - DOMElement* targetElement -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs -#endif - ) const -{ - if (getElementQName().hasPrefix()) - targetElement->setPrefix(getElementQName().getPrefix()); - - if (m_schemaLocation) { - static const XMLCh schemaLocation[]= UNICODE_LITERAL_14(s,c,h,e,m,a,L,o,c,a,t,i,o,n); - if (targetElement->getParentNode()==NULL || targetElement->getParentNode()->getNodeType()==DOMNode::DOCUMENT_NODE) - targetElement->setAttributeNS(XMLConstants::XSI_NS,schemaLocation,m_schemaLocation); - } - - marshallElementType(targetElement); - marshallNamespaces(targetElement); - marshallAttributes(targetElement); - marshallContent(targetElement); - -#ifndef XMLTOOLING_NO_XMLSEC - if (sigs) { - for_each(sigs->begin(),sigs->end(),mem_fun(&Signature::sign)); - } -#endif -} - -void AbstractXMLObjectMarshaller::marshallElementType(DOMElement* domElement) const -{ - const QName* type = getSchemaType(); - if (type) { - XT_log.debug("setting xsi:type attribute for XMLObject"); - - const XMLCh* typeLocalName = type->getLocalPart(); - if (!typeLocalName || !*typeLocalName) { - throw MarshallingException("Schema type of XMLObject may not have an empty local name."); - } - - static const XMLCh xsitype[] = { - chLatin_x, chLatin_s, chLatin_i, chColon, chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull - }; - - XMLCh* xsivalue=const_cast(typeLocalName); - const XMLCh* prefix=type->getPrefix(); - if (prefix && *prefix) { - xsivalue=new XMLCh[XMLString::stringLen(typeLocalName) + XMLString::stringLen(prefix) + 2*sizeof(XMLCh)]; - *xsivalue=chNull; - XMLString::catString(xsivalue,prefix); - static const XMLCh colon[] = {chColon, chNull}; - XMLString::catString(xsivalue,colon); - XMLString::catString(xsivalue,typeLocalName); - } - domElement->setAttributeNS(XMLConstants::XSI_NS, xsitype, xsivalue); - if (xsivalue != typeLocalName) - XMLString::release(&xsivalue); - - XT_log.debug("Adding XSI namespace to list of namespaces used by XMLObject"); - addNamespace(Namespace(XMLConstants::XSI_NS, XMLConstants::XSI_PREFIX)); - } -} - -class _addns : public binary_function { -public: - void operator()(DOMElement* domElement, const Namespace& ns) const { - const XMLCh* prefix=ns.getNamespacePrefix(); - const XMLCh* uri=ns.getNamespaceURI(); - - // Check to see if the prefix is already declared properly above this node. - if (!ns.alwaysDeclare()) { - const XMLCh* declared=lookupNamespaceURI(domElement->getParentNode(),prefix); - if (declared && XMLString::equals(declared,uri)) - return; - } - - if (prefix && *prefix) { - XMLCh* xmlns=new XMLCh[XMLString::stringLen(XMLConstants::XMLNS_PREFIX) + XMLString::stringLen(prefix) + 2*sizeof(XMLCh)]; - *xmlns=chNull; - XMLString::catString(xmlns,XMLConstants::XMLNS_PREFIX); - static const XMLCh colon[] = {chColon, chNull}; - XMLString::catString(xmlns,colon); - XMLString::catString(xmlns,prefix); - domElement->setAttributeNS(XMLConstants::XMLNS_NS, xmlns, uri); - } - else { - domElement->setAttributeNS(XMLConstants::XMLNS_NS, XMLConstants::XMLNS_PREFIX, uri); - } - } - - const XMLCh* lookupNamespaceURI(const DOMNode* n, const XMLCh* prefix) const { - // Return NULL if no declaration in effect. The empty string signifies the null namespace. - if (!n || n->getNodeType()!=DOMNode::ELEMENT_NODE) { - // At the root, the default namespace is set to the null namespace. - if (!prefix || !*prefix) - return &chNull; - return NULL; // we're done - } - DOMNamedNodeMap* attributes = static_cast(n)->getAttributes(); - if (!attributes) - return lookupNamespaceURI(n->getParentNode(),prefix); // defer to parent - DOMNode* childNode; - DOMAttr* attribute; - for (XMLSize_t i=0; igetLength(); i++) { - childNode = attributes->item(i); - if (childNode->getNodeType() != DOMNode::ATTRIBUTE_NODE) // not an attribute? - continue; - attribute = static_cast(childNode); - if (!XMLString::equals(attribute->getNamespaceURI(),XMLConstants::XMLNS_NS)) - continue; // not a namespace declaration - // Local name should be the prefix and the value would be the URI, except for the default namespace. - if ((!prefix || !*prefix) && XMLString::equals(attribute->getLocalName(),XMLConstants::XMLNS_PREFIX)) - return attribute->getNodeValue(); - else if (XMLString::equals(prefix,attribute->getLocalName())) - return attribute->getNodeValue(); - } - // Defer to parent. - return lookupNamespaceURI(n->getParentNode(),prefix); - } -}; - -void AbstractXMLObjectMarshaller::marshallNamespaces(DOMElement* domElement) const -{ - XT_log.debug("marshalling namespace attributes for XMLObject"); - const set& namespaces = getNamespaces(); - for_each(namespaces.begin(),namespaces.end(),bind1st(_addns(),domElement)); -} - -void AbstractXMLObjectMarshaller::marshallContent(DOMElement* domElement) const -{ - XT_log.debug("marshalling text and child elements for XMLObject"); - - const XMLCh* val; - unsigned int pos=0; - const list& children=getOrderedChildren(); - for (list::const_iterator i=children.begin(); i!=children.end(); ++i, ++pos) { - val = getTextContent(pos); - if (val && *val) - domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val)); - if (*i) - (*i)->marshall(domElement); - } - val = getTextContent(pos); - if (val && *val) - domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val)); -} +/* +* 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. + */ + +/** + * AbstractXMLObjectMarshaller.cpp + * + * A thread-safe abstract marshaller. + */ + +#include "internal.h" +#include "exceptions.h" +#include "io/AbstractXMLObjectMarshaller.h" +#ifndef XMLTOOLING_NO_XMLSEC + #include "signature/Signature.h" +#endif +#include "util/NDC.h" +#include "util/XMLConstants.h" +#include "util/XMLHelper.h" + +#include +#include +#include +#include + +#ifndef XMLTOOLING_NO_XMLSEC + using namespace xmlsignature; +#endif +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +#define XT_log (*static_cast(m_log)) + +DOMElement* AbstractXMLObjectMarshaller::marshall( + DOMDocument* document +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs +#endif + ) const +{ +#ifdef _DEBUG + xmltooling::NDC ndc("marshall"); +#endif + + if (XT_log.isDebugEnabled()) { + XT_log.debug("starting to marshal %s", getElementQName().toString().c_str()); + } + + DOMElement* cachedDOM=getDOM(); + if (cachedDOM) { + if (!document || document==cachedDOM->getOwnerDocument()) { + XT_log.debug("XMLObject has a usable cached DOM, reusing it"); + if (document) + setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM); + releaseParentDOM(true); + return cachedDOM; + } + + // We have a DOM but it doesn't match the document we were given. This both sucks and blows. + // Without an adoptNode option to maintain the child pointers, we have to either import the + // DOM while somehow reassigning all the nested references (which amounts to a complete + // *unmarshall* operation), or we just release the existing DOM and hope that we can get + // it back. This depends on all objects being able to preserve their DOM at all costs. + releaseChildrenDOM(true); + releaseDOM(); + } + + // If we get here, we didn't have a usable DOM (and/or we released the one we had). + // We may need to create our own document. + bool bindDocument=false; + if (!document) { + document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument(); + bindDocument=true; + } + + XercesJanitor janitor(bindDocument ? document : NULL); + + XT_log.debug("creating root element to marshall"); + DOMElement* domElement = document->createElementNS( + getElementQName().getNamespaceURI(), getElementQName().getLocalPart() + ); + setDocumentElement(document, domElement); +#ifndef XMLTOOLING_NO_XMLSEC + marshallInto(domElement, sigs); +#else + marshallInto(domElement); +#endif + //Recache the DOM. + XT_log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not "); + setDOM(domElement, bindDocument); + janitor.release(); // safely transferred + releaseParentDOM(true); + + return domElement; +} + +DOMElement* AbstractXMLObjectMarshaller::marshall( + DOMElement* parentElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs +#endif + ) const +{ +#ifdef _DEBUG + xmltooling::NDC ndc("marshall"); +#endif + + if (XT_log.isDebugEnabled()) { + XT_log.debug("starting to marshalling %s", getElementQName().toString().c_str()); + } + + DOMElement* cachedDOM=getDOM(); + if (cachedDOM) { + if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { + XT_log.debug("XMLObject has a usable cached DOM, reusing it"); + if (parentElement!=cachedDOM->getParentNode()) { + parentElement->appendChild(cachedDOM); + releaseParentDOM(true); + } + return cachedDOM; + } + + // We have a DOM but it doesn't match the document we were given. This both sucks and blows. + // Without an adoptNode option to maintain the child pointers, we have to either import the + // DOM while somehow reassigning all the nested references (which amounts to a complete + // *unmarshall* operation), or we just release the existing DOM and hope that we can get + // it back. This depends on all objects being able to preserve their DOM at all costs. + releaseChildrenDOM(true); + releaseDOM(); + } + + // If we get here, we didn't have a usable DOM (and/or we released the one we had). + XT_log.debug("creating root element to marshall"); + DOMElement* domElement = parentElement->getOwnerDocument()->createElementNS( + getElementQName().getNamespaceURI(), getElementQName().getLocalPart() + ); + parentElement->appendChild(domElement); +#ifndef XMLTOOLING_NO_XMLSEC + marshallInto(domElement, sigs); +#else + marshallInto(domElement); +#endif + + //Recache the DOM. + XT_log.debug("caching DOM for XMLObject"); + setDOM(domElement, false); + releaseParentDOM(true); + + return domElement; +} + +void AbstractXMLObjectMarshaller::marshallInto( + DOMElement* targetElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs +#endif + ) const +{ + if (getElementQName().hasPrefix()) + targetElement->setPrefix(getElementQName().getPrefix()); + + if (m_schemaLocation) { + static const XMLCh schemaLocation[]= UNICODE_LITERAL_14(s,c,h,e,m,a,L,o,c,a,t,i,o,n); + if (targetElement->getParentNode()==NULL || targetElement->getParentNode()->getNodeType()==DOMNode::DOCUMENT_NODE) + targetElement->setAttributeNS(XMLConstants::XSI_NS,schemaLocation,m_schemaLocation); + } + + marshallElementType(targetElement); + marshallNamespaces(targetElement); + marshallAttributes(targetElement); + marshallContent(targetElement); + +#ifndef XMLTOOLING_NO_XMLSEC + if (sigs) { + for_each(sigs->begin(),sigs->end(),mem_fun(&Signature::sign)); + } +#endif +} + +void AbstractXMLObjectMarshaller::marshallElementType(DOMElement* domElement) const +{ + const QName* type = getSchemaType(); + if (type) { + XT_log.debug("setting xsi:type attribute for XMLObject"); + + const XMLCh* typeLocalName = type->getLocalPart(); + if (!typeLocalName || !*typeLocalName) { + throw MarshallingException("Schema type of XMLObject may not have an empty local name."); + } + + static const XMLCh xsitype[] = { + chLatin_x, chLatin_s, chLatin_i, chColon, chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull + }; + + XMLCh* xsivalue=const_cast(typeLocalName); + const XMLCh* prefix=type->getPrefix(); + if (prefix && *prefix) { + xsivalue=new XMLCh[XMLString::stringLen(typeLocalName) + XMLString::stringLen(prefix) + 2*sizeof(XMLCh)]; + *xsivalue=chNull; + XMLString::catString(xsivalue,prefix); + static const XMLCh colon[] = {chColon, chNull}; + XMLString::catString(xsivalue,colon); + XMLString::catString(xsivalue,typeLocalName); + } + domElement->setAttributeNS(XMLConstants::XSI_NS, xsitype, xsivalue); + if (xsivalue != typeLocalName) + XMLString::release(&xsivalue); + + XT_log.debug("Adding XSI namespace to list of namespaces used by XMLObject"); + addNamespace(Namespace(XMLConstants::XSI_NS, XMLConstants::XSI_PREFIX)); + } +} + +class _addns : public binary_function { +public: + void operator()(DOMElement* domElement, const Namespace& ns) const { + const XMLCh* prefix=ns.getNamespacePrefix(); + const XMLCh* uri=ns.getNamespaceURI(); + + // Check to see if the prefix is already declared properly above this node. + if (!ns.alwaysDeclare()) { + const XMLCh* declared=lookupNamespaceURI(domElement->getParentNode(),prefix); + if (declared && XMLString::equals(declared,uri)) + return; + } + + if (prefix && *prefix) { + XMLCh* xmlns=new XMLCh[XMLString::stringLen(XMLConstants::XMLNS_PREFIX) + XMLString::stringLen(prefix) + 2*sizeof(XMLCh)]; + *xmlns=chNull; + XMLString::catString(xmlns,XMLConstants::XMLNS_PREFIX); + static const XMLCh colon[] = {chColon, chNull}; + XMLString::catString(xmlns,colon); + XMLString::catString(xmlns,prefix); + domElement->setAttributeNS(XMLConstants::XMLNS_NS, xmlns, uri); + } + else { + domElement->setAttributeNS(XMLConstants::XMLNS_NS, XMLConstants::XMLNS_PREFIX, uri); + } + } + + const XMLCh* lookupNamespaceURI(const DOMNode* n, const XMLCh* prefix) const { + // Return NULL if no declaration in effect. The empty string signifies the null namespace. + if (!n || n->getNodeType()!=DOMNode::ELEMENT_NODE) { + // At the root, the default namespace is set to the null namespace. + if (!prefix || !*prefix) + return &chNull; + return NULL; // we're done + } + DOMNamedNodeMap* attributes = static_cast(n)->getAttributes(); + if (!attributes) + return lookupNamespaceURI(n->getParentNode(),prefix); // defer to parent + DOMNode* childNode; + DOMAttr* attribute; + for (XMLSize_t i=0; igetLength(); i++) { + childNode = attributes->item(i); + if (childNode->getNodeType() != DOMNode::ATTRIBUTE_NODE) // not an attribute? + continue; + attribute = static_cast(childNode); + if (!XMLString::equals(attribute->getNamespaceURI(),XMLConstants::XMLNS_NS)) + continue; // not a namespace declaration + // Local name should be the prefix and the value would be the URI, except for the default namespace. + if ((!prefix || !*prefix) && XMLString::equals(attribute->getLocalName(),XMLConstants::XMLNS_PREFIX)) + return attribute->getNodeValue(); + else if (XMLString::equals(prefix,attribute->getLocalName())) + return attribute->getNodeValue(); + } + // Defer to parent. + return lookupNamespaceURI(n->getParentNode(),prefix); + } +}; + +void AbstractXMLObjectMarshaller::marshallNamespaces(DOMElement* domElement) const +{ + XT_log.debug("marshalling namespace attributes for XMLObject"); + const set& namespaces = getNamespaces(); + for_each(namespaces.begin(),namespaces.end(),bind1st(_addns(),domElement)); +} + +void AbstractXMLObjectMarshaller::marshallContent(DOMElement* domElement) const +{ + XT_log.debug("marshalling text and child elements for XMLObject"); + + const XMLCh* val; + unsigned int pos=0; + const list& children=getOrderedChildren(); + for (list::const_iterator i=children.begin(); i!=children.end(); ++i, ++pos) { + val = getTextContent(pos); + if (val && *val) + domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val)); + if (*i) + (*i)->marshall(domElement); + } + val = getTextContent(pos); + if (val && *val) + domElement->appendChild(domElement->getOwnerDocument()->createTextNode(val)); +} diff --git a/xmltooling/io/AbstractXMLObjectMarshaller.h b/xmltooling/io/AbstractXMLObjectMarshaller.h index cbab2fe..5cea6ae 100644 --- a/xmltooling/io/AbstractXMLObjectMarshaller.h +++ b/xmltooling/io/AbstractXMLObjectMarshaller.h @@ -1,134 +1,134 @@ -/* -* 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 AbstractXMLObjectMarshaller.h - * - * A thread-safe abstract marshaller. - */ - -#if !defined(__xmltooling_xmlmarshaller_h__) -#define __xmltooling_xmlmarshaller_h__ - -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * A thread-safe abstract marshaller. - */ - class XMLTOOL_API AbstractXMLObjectMarshaller : public virtual AbstractXMLObject - { - public: - virtual ~AbstractXMLObjectMarshaller() {} - - DOMElement* marshall( - DOMDocument* document=NULL -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs=NULL -#endif - ) const; - - DOMElement* marshall( - DOMElement* parentElement -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs=NULL -#endif - ) const; - - protected: - AbstractXMLObjectMarshaller() {} - - /** - * Sets the given element as the Document Element of the given Document. - * If the document already has a Document Element it is replaced by the given element. - * - * @param document the document - * @param element the Element that will serve as the Document Element - */ - void setDocumentElement(DOMDocument* document, DOMElement* element) const { - DOMElement* documentRoot = document->getDocumentElement(); - if (documentRoot) - document->replaceChild(element, documentRoot); - else - document->appendChild(element); - } - - /** - * Marshalls the XMLObject into the given DOM Element. - * The DOM Element must be within a DOM tree rooted in the owning Document. - * - * @param targetElement the Element into which the XMLObject is marshalled into - * @param ctx optional marshalling context - * - * @throws MarshallingException thrown if there is a problem marshalling the object - * @throws SignatureException thrown if a problem occurs during signature creation - */ - void marshallInto( - DOMElement* targetElement -#ifndef XMLTOOLING_NO_XMLSEC - ,const std::vector* sigs -#endif - ) const; - - /** - * Creates an xsi:type attribute, corresponding to the given type of the XMLObject, on the DOM element. - * - * @param domElement the DOM element - * - * @throws MarshallingException thrown if the type on the XMLObject is doesn't contain - * a local name, prefix, and namespace URI - */ - void marshallElementType(DOMElement* domElement) const; - - /** - * Creates the xmlns attributes for any namespaces set on the XMLObject. - * - * @param domElement the DOM element the namespaces will be added to - */ - void marshallNamespaces(DOMElement* domElement) const; - - /** - * Marshalls the text content and/or child elements of the XMLObject. - * - * @param domElement the DOM element that will recieved the marshalled children - * - * @throws MarshallingException thrown if there is a problem marshalling a child element - */ - void marshallContent(DOMElement* domElement) const; - - /** - * Marshalls the attributes from the XMLObject into the given DOM element. - * - * @param domElement the DOM Element into which attributes will be marshalled - * - * @throws MarshallingException thrown if there is a problem marshalling an attribute - */ - virtual void marshallAttributes(DOMElement* domElement) const {} - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_xmlmarshaller_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 AbstractXMLObjectMarshaller.h + * + * A thread-safe abstract marshaller. + */ + +#if !defined(__xmltooling_xmlmarshaller_h__) +#define __xmltooling_xmlmarshaller_h__ + +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * A thread-safe abstract marshaller. + */ + class XMLTOOL_API AbstractXMLObjectMarshaller : public virtual AbstractXMLObject + { + public: + virtual ~AbstractXMLObjectMarshaller() {} + + DOMElement* marshall( + DOMDocument* document=NULL +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const; + + DOMElement* marshall( + DOMElement* parentElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const; + + protected: + AbstractXMLObjectMarshaller() {} + + /** + * Sets the given element as the Document Element of the given Document. + * If the document already has a Document Element it is replaced by the given element. + * + * @param document the document + * @param element the Element that will serve as the Document Element + */ + void setDocumentElement(DOMDocument* document, DOMElement* element) const { + DOMElement* documentRoot = document->getDocumentElement(); + if (documentRoot) + document->replaceChild(element, documentRoot); + else + document->appendChild(element); + } + + /** + * Marshalls the XMLObject into the given DOM Element. + * The DOM Element must be within a DOM tree rooted in the owning Document. + * + * @param targetElement the Element into which the XMLObject is marshalled into + * @param ctx optional marshalling context + * + * @throws MarshallingException thrown if there is a problem marshalling the object + * @throws SignatureException thrown if a problem occurs during signature creation + */ + void marshallInto( + DOMElement* targetElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs +#endif + ) const; + + /** + * Creates an xsi:type attribute, corresponding to the given type of the XMLObject, on the DOM element. + * + * @param domElement the DOM element + * + * @throws MarshallingException thrown if the type on the XMLObject is doesn't contain + * a local name, prefix, and namespace URI + */ + void marshallElementType(DOMElement* domElement) const; + + /** + * Creates the xmlns attributes for any namespaces set on the XMLObject. + * + * @param domElement the DOM element the namespaces will be added to + */ + void marshallNamespaces(DOMElement* domElement) const; + + /** + * Marshalls the text content and/or child elements of the XMLObject. + * + * @param domElement the DOM element that will recieved the marshalled children + * + * @throws MarshallingException thrown if there is a problem marshalling a child element + */ + void marshallContent(DOMElement* domElement) const; + + /** + * Marshalls the attributes from the XMLObject into the given DOM element. + * + * @param domElement the DOM Element into which attributes will be marshalled + * + * @throws MarshallingException thrown if there is a problem marshalling an attribute + */ + virtual void marshallAttributes(DOMElement* domElement) const {} + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_xmlmarshaller_h__ */ diff --git a/xmltooling/io/AbstractXMLObjectUnmarshaller.h b/xmltooling/io/AbstractXMLObjectUnmarshaller.h index 80d0909..a69ef1b 100644 --- a/xmltooling/io/AbstractXMLObjectUnmarshaller.h +++ b/xmltooling/io/AbstractXMLObjectUnmarshaller.h @@ -1,96 +1,96 @@ -/* -* 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 AbstractXMLObjectUnmarshaller.h - * - * A thread-safe abstract unmarshaller. - */ - -#ifndef __xmltooling_xmlunmarshaller_h__ -#define __xmltooling_xmlunmarshaller_h__ - -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * A thread-safe abstract unmarshaller. - */ - class XMLTOOL_API AbstractXMLObjectUnmarshaller : public virtual AbstractXMLObject - { - public: - virtual ~AbstractXMLObjectUnmarshaller() {} - - XMLObject* unmarshall(DOMElement* element, bool bindDocument=false); - - protected: - AbstractXMLObjectUnmarshaller() {} - - /** - * Unmarshalls the attributes from the given DOM Element into the XMLObject. If the attribute - * is an XML namespace declaration the namespace is added via XMLObject::addNamespace(). - * If it is a schema type (xsi:type) the schema type is added via XMLObject::setSchemaType(). - * All other attributes are passed to the processAttribute hook. - * - * @param domElement the DOM Element whose attributes will be unmarshalled - * - * @throws UnmarshallingException thrown if there is a problem unmarshalling an attribute - */ - virtual void unmarshallAttributes(const DOMElement* domElement); - - /** - * Unmarshalls a given Element's child nodes. The resulting XMLObject children and content - * are passed to processChildElement() or processText() for further processing. - * - * @param domElement the DOM Element whose children will be unmarshalled - * - * @throws UnmarshallingException thrown if an error occurs unmarshalling the child elements - */ - virtual void unmarshallContent(const DOMElement* domElement); - - /** - * Called after a child element has been unmarshalled so that it can be added to the parent XMLObject. - * - * @param child pointer to the child XMLObject - * @param childRoot root element of the child (must not be stored, just a hint) - * - * @throws UnmarshallingException thrown if there is a problem adding the child to the parent - */ - virtual void processChildElement(XMLObject* child, const DOMElement* childRoot); - - /** - * Called after an attribute has been unmarshalled so that it can be added to the XMLObject. - * - * @param attribute the attribute being unmarshalled - * - * @throws UnmarshallingException thrown if there is a problem adding the attribute to the XMLObject - */ - virtual void processAttribute(const DOMAttr* attribute); - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_xmlunmarshaller_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 AbstractXMLObjectUnmarshaller.h + * + * A thread-safe abstract unmarshaller. + */ + +#ifndef __xmltooling_xmlunmarshaller_h__ +#define __xmltooling_xmlunmarshaller_h__ + +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * A thread-safe abstract unmarshaller. + */ + class XMLTOOL_API AbstractXMLObjectUnmarshaller : public virtual AbstractXMLObject + { + public: + virtual ~AbstractXMLObjectUnmarshaller() {} + + XMLObject* unmarshall(DOMElement* element, bool bindDocument=false); + + protected: + AbstractXMLObjectUnmarshaller() {} + + /** + * Unmarshalls the attributes from the given DOM Element into the XMLObject. If the attribute + * is an XML namespace declaration the namespace is added via XMLObject::addNamespace(). + * If it is a schema type (xsi:type) the schema type is added via XMLObject::setSchemaType(). + * All other attributes are passed to the processAttribute hook. + * + * @param domElement the DOM Element whose attributes will be unmarshalled + * + * @throws UnmarshallingException thrown if there is a problem unmarshalling an attribute + */ + virtual void unmarshallAttributes(const DOMElement* domElement); + + /** + * Unmarshalls a given Element's child nodes. The resulting XMLObject children and content + * are passed to processChildElement() or processText() for further processing. + * + * @param domElement the DOM Element whose children will be unmarshalled + * + * @throws UnmarshallingException thrown if an error occurs unmarshalling the child elements + */ + virtual void unmarshallContent(const DOMElement* domElement); + + /** + * Called after a child element has been unmarshalled so that it can be added to the parent XMLObject. + * + * @param child pointer to the child XMLObject + * @param childRoot root element of the child (must not be stored, just a hint) + * + * @throws UnmarshallingException thrown if there is a problem adding the child to the parent + */ + virtual void processChildElement(XMLObject* child, const DOMElement* childRoot); + + /** + * Called after an attribute has been unmarshalled so that it can be added to the XMLObject. + * + * @param attribute the attribute being unmarshalled + * + * @throws UnmarshallingException thrown if there is a problem adding the attribute to the XMLObject + */ + virtual void processAttribute(const DOMAttr* attribute); + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_xmlunmarshaller_h__ */ diff --git a/xmltooling/security/OpenSSLCryptoX509CRL.h b/xmltooling/security/OpenSSLCryptoX509CRL.h index a689ebf..ac3c090 100644 --- a/xmltooling/security/OpenSSLCryptoX509CRL.h +++ b/xmltooling/security/OpenSSLCryptoX509CRL.h @@ -1,66 +1,66 @@ -/* - * Copyright 2006 The Apache Software Foundation. - * - * 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. - */ - -/** - * OpenSSLCryptoX509CRL.h - * - * OpenSSL-based class for handling X.509 CRLs - */ - -#if !defined(__xmltooling_opensslx509crl_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_opensslx509crl_h__ - -#include - -#include -#include -#include - -namespace xmltooling { - class XMLTOOL_API OpenSSLCryptoX509CRL : public XSECCryptoX509CRL { - public: - OpenSSLCryptoX509CRL() : mp_X509CRL(NULL), m_DERX509CRL("") {} - virtual ~OpenSSLCryptoX509CRL(); - - virtual const XMLCh* getProviderName() const { - return DSIGConstants::s_unicodeStrPROVOpenSSL; - } - virtual void loadX509CRLBase64Bin(const char* buf, unsigned int len); - - virtual safeBuffer& getDEREncodingSB(void) { - return m_DERX509CRL; - } - - OpenSSLCryptoX509CRL(X509_CRL* x); - X509_CRL* getOpenSSLX509CRL(void) { - return mp_X509CRL; - } - - XSECCryptoX509CRL* clone() const { - OpenSSLCryptoX509CRL* copy = new OpenSSLCryptoX509CRL(); - copy->mp_X509CRL = X509_CRL_dup(mp_X509CRL); - copy->m_DERX509CRL = m_DERX509CRL; - return copy; - } - - private: - X509_CRL* mp_X509CRL; - safeBuffer m_DERX509CRL; - }; -}; - -#endif /* __xmltooling_opensslx509crl_h__ */ - +/* + * Copyright 2006 The Apache Software Foundation. + * + * 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. + */ + +/** + * OpenSSLCryptoX509CRL.h + * + * OpenSSL-based class for handling X.509 CRLs + */ + +#if !defined(__xmltooling_opensslx509crl_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_opensslx509crl_h__ + +#include + +#include +#include +#include + +namespace xmltooling { + class XMLTOOL_API OpenSSLCryptoX509CRL : public XSECCryptoX509CRL { + public: + OpenSSLCryptoX509CRL() : mp_X509CRL(NULL), m_DERX509CRL("") {} + virtual ~OpenSSLCryptoX509CRL(); + + virtual const XMLCh* getProviderName() const { + return DSIGConstants::s_unicodeStrPROVOpenSSL; + } + virtual void loadX509CRLBase64Bin(const char* buf, unsigned int len); + + virtual safeBuffer& getDEREncodingSB(void) { + return m_DERX509CRL; + } + + OpenSSLCryptoX509CRL(X509_CRL* x); + X509_CRL* getOpenSSLX509CRL(void) { + return mp_X509CRL; + } + + XSECCryptoX509CRL* clone() const { + OpenSSLCryptoX509CRL* copy = new OpenSSLCryptoX509CRL(); + copy->mp_X509CRL = X509_CRL_dup(mp_X509CRL); + copy->m_DERX509CRL = m_DERX509CRL; + return copy; + } + + private: + X509_CRL* mp_X509CRL; + safeBuffer m_DERX509CRL; + }; +}; + +#endif /* __xmltooling_opensslx509crl_h__ */ + diff --git a/xmltooling/security/TrustEngine.h b/xmltooling/security/TrustEngine.h index abc887f..33049a0 100644 --- a/xmltooling/security/TrustEngine.h +++ b/xmltooling/security/TrustEngine.h @@ -1,118 +1,118 @@ -/* - * 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 xmltooling/security/TrustEngine.h - * - * Evaluates the trustworthiness and validity of XML Signatures against - * implementation-specific requirements. - */ - -#if !defined(__xmltooling_trust_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_trust_h__ - -#include -#include - -namespace xmltooling { - - /** - * Evaluates the trustworthiness and validity of XML Signatures against - * implementation-specific requirements. - */ - class XMLTOOL_API TrustEngine { - MAKE_NONCOPYABLE(TrustEngine); - protected: - /** - * Constructor. - * - * If a DOM is supplied, the following XML content is supported: - * - *
    - *
  • <KeyResolver> elements with a type attribute - *
- * - * XML namespaces are ignored in the processing of this content. - * - * @param e DOM to supply configuration for provider - */ - TrustEngine(const DOMElement* e=NULL); - - /** Default KeyResolver instance. */ - xmlsignature::KeyResolver* m_keyResolver; - - public: - virtual ~TrustEngine(); - - /** - * Callback interface to supply KeyInfo objects to a TrustEngine. - * Applications can adapt TrustEngines to their environment by supplying - * implementations of this interface, or create specialized TrustEngine APIs - * by combining a KeyInfoIterator with a delegated TrustEngine. - */ - class XMLTOOL_API KeyInfoIterator { - MAKE_NONCOPYABLE(KeyInfoIterator); - protected: - KeyInfoIterator() {} - public: - virtual ~KeyInfoIterator() {} - - /** - * Indicates whether additional KeyInfo objects are available. - * - * @return true iff another KeyInfo object can be fetched - */ - virtual bool hasNext() const=0; - - /** - * Returns the next KeyInfo object available. - * - * @return the next KeyInfo object, or NULL if none are left - */ - virtual const xmlsignature::KeyInfo* next()=0; - }; - - /** - * Determines whether a signature is correct and valid with respect to the - * KeyInfo data supplied. It is the responsibility of the application to - * ensure that the KeyInfo information supplied is in fact associated with - * the peer who created the signature. - * - * A custom KeyResolver can be supplied from outside the TrustEngine. - * Alternatively, one may be specified to the plugin constructor. - * A non-caching, inline resolver will be used as a fallback. - * - * @param sig reference to a signature object to validate - * @param keyInfoSource supplies KeyInfo objects to the TrustEngine - * @param keyResolver optional externally supplied KeyResolver, or NULL - */ - virtual bool validate( - xmlsignature::Signature& sig, - KeyInfoIterator& keyInfoSource, - const xmlsignature::KeyResolver* keyResolver=NULL - ) const=0; - }; - - /** - * Registers TrustEngine classes into the runtime. - */ - void XMLTOOL_API registerTrustEngines(); - - /** TrustEngine based on explicit knowledge of peer key information. */ - #define EXPLICIT_KEY_TRUSTENGINE "org.opensaml.xmlooling.security.ExplicitKeyTrustEngine" -}; - -#endif /* __xmltooling_trust_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 xmltooling/security/TrustEngine.h + * + * Evaluates the trustworthiness and validity of XML Signatures against + * implementation-specific requirements. + */ + +#if !defined(__xmltooling_trust_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_trust_h__ + +#include +#include + +namespace xmltooling { + + /** + * Evaluates the trustworthiness and validity of XML Signatures against + * implementation-specific requirements. + */ + class XMLTOOL_API TrustEngine { + MAKE_NONCOPYABLE(TrustEngine); + protected: + /** + * Constructor. + * + * If a DOM is supplied, the following XML content is supported: + * + *
    + *
  • <KeyResolver> elements with a type attribute + *
+ * + * XML namespaces are ignored in the processing of this content. + * + * @param e DOM to supply configuration for provider + */ + TrustEngine(const DOMElement* e=NULL); + + /** Default KeyResolver instance. */ + xmlsignature::KeyResolver* m_keyResolver; + + public: + virtual ~TrustEngine(); + + /** + * Callback interface to supply KeyInfo objects to a TrustEngine. + * Applications can adapt TrustEngines to their environment by supplying + * implementations of this interface, or create specialized TrustEngine APIs + * by combining a KeyInfoIterator with a delegated TrustEngine. + */ + class XMLTOOL_API KeyInfoIterator { + MAKE_NONCOPYABLE(KeyInfoIterator); + protected: + KeyInfoIterator() {} + public: + virtual ~KeyInfoIterator() {} + + /** + * Indicates whether additional KeyInfo objects are available. + * + * @return true iff another KeyInfo object can be fetched + */ + virtual bool hasNext() const=0; + + /** + * Returns the next KeyInfo object available. + * + * @return the next KeyInfo object, or NULL if none are left + */ + virtual const xmlsignature::KeyInfo* next()=0; + }; + + /** + * Determines whether a signature is correct and valid with respect to the + * KeyInfo data supplied. It is the responsibility of the application to + * ensure that the KeyInfo information supplied is in fact associated with + * the peer who created the signature. + * + * A custom KeyResolver can be supplied from outside the TrustEngine. + * Alternatively, one may be specified to the plugin constructor. + * A non-caching, inline resolver will be used as a fallback. + * + * @param sig reference to a signature object to validate + * @param keyInfoSource supplies KeyInfo objects to the TrustEngine + * @param keyResolver optional externally supplied KeyResolver, or NULL + */ + virtual bool validate( + xmlsignature::Signature& sig, + KeyInfoIterator& keyInfoSource, + const xmlsignature::KeyResolver* keyResolver=NULL + ) const=0; + }; + + /** + * Registers TrustEngine classes into the runtime. + */ + void XMLTOOL_API registerTrustEngines(); + + /** TrustEngine based on explicit knowledge of peer key information. */ + #define EXPLICIT_KEY_TRUSTENGINE "org.opensaml.xmlooling.security.ExplicitKeyTrustEngine" +}; + +#endif /* __xmltooling_trust_h__ */ diff --git a/xmltooling/security/X509TrustEngine.h b/xmltooling/security/X509TrustEngine.h index b0b2cf8..3aabe05 100644 --- a/xmltooling/security/X509TrustEngine.h +++ b/xmltooling/security/X509TrustEngine.h @@ -1,80 +1,80 @@ -/* - * 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 xmltooling/security/X509TrustEngine.h - * - * Extended TrustEngine interface that adds validation of X.509 credentials. - */ - -#if !defined(__xmltooling_x509trust_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_x509trust_h__ - -#include - -namespace xmltooling { - - /** - * Extended TrustEngine interface that adds validation of X.509 credentials. - */ - class XMLTOOL_API X509TrustEngine : public TrustEngine { - protected: - /** - * Constructor. - * - * If a DOM is supplied, the following XML content is supported: - * - *
    - *
  • <KeyResolver> elements with a type attribute - *
- * - * XML namespaces are ignored in the processing of this content. - * - * @param e DOM to supply configuration for provider - */ - X509TrustEngine(const DOMElement* e=NULL) : TrustEngine(e) {} - - public: - virtual ~X509TrustEngine() {} - - /** - * Determines whether an X.509 credential is valid with respect to the - * KeyInfo data supplied. It is the responsibility of the application to - * ensure that the KeyInfo information supplied is in fact associated with - * the peer who presented the signature. - * - * A custom KeyResolver can be supplied from outside the TrustEngine. - * Alternatively, one may be specified to the plugin constructor. - * A non-caching, inline resolver will be used as a fallback. - * - * @param certEE end-entity certificate to validate - * @param certChain the complete set of certificates presented for validation (includes certEE) - * @param keyInfoSource supplies KeyInfo objects to the TrustEngine - * @param checkName true iff certificate subject/name checking has NOT already occurred - * @param keyResolver optional externally supplied KeyResolver, or NULL - */ - virtual bool validate( - XSECCryptoX509* certEE, - const std::vector& certChain, - TrustEngine::KeyInfoIterator& keyInfoSource, - bool checkName=true, - const xmlsignature::KeyResolver* keyResolver=NULL - ) const=0; - }; - -}; - -#endif /* __xmltooling_x509trust_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 xmltooling/security/X509TrustEngine.h + * + * Extended TrustEngine interface that adds validation of X.509 credentials. + */ + +#if !defined(__xmltooling_x509trust_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_x509trust_h__ + +#include + +namespace xmltooling { + + /** + * Extended TrustEngine interface that adds validation of X.509 credentials. + */ + class XMLTOOL_API X509TrustEngine : public TrustEngine { + protected: + /** + * Constructor. + * + * If a DOM is supplied, the following XML content is supported: + * + *
    + *
  • <KeyResolver> elements with a type attribute + *
+ * + * XML namespaces are ignored in the processing of this content. + * + * @param e DOM to supply configuration for provider + */ + X509TrustEngine(const DOMElement* e=NULL) : TrustEngine(e) {} + + public: + virtual ~X509TrustEngine() {} + + /** + * Determines whether an X.509 credential is valid with respect to the + * KeyInfo data supplied. It is the responsibility of the application to + * ensure that the KeyInfo information supplied is in fact associated with + * the peer who presented the signature. + * + * A custom KeyResolver can be supplied from outside the TrustEngine. + * Alternatively, one may be specified to the plugin constructor. + * A non-caching, inline resolver will be used as a fallback. + * + * @param certEE end-entity certificate to validate + * @param certChain the complete set of certificates presented for validation (includes certEE) + * @param keyInfoSource supplies KeyInfo objects to the TrustEngine + * @param checkName true iff certificate subject/name checking has NOT already occurred + * @param keyResolver optional externally supplied KeyResolver, or NULL + */ + virtual bool validate( + XSECCryptoX509* certEE, + const std::vector& certChain, + TrustEngine::KeyInfoIterator& keyInfoSource, + bool checkName=true, + const xmlsignature::KeyResolver* keyResolver=NULL + ) const=0; + }; + +}; + +#endif /* __xmltooling_x509trust_h__ */ diff --git a/xmltooling/security/XSECCryptoX509CRL.h b/xmltooling/security/XSECCryptoX509CRL.h index 4bca77b..fd67f20 100644 --- a/xmltooling/security/XSECCryptoX509CRL.h +++ b/xmltooling/security/XSECCryptoX509CRL.h @@ -1,88 +1,88 @@ -/* - * Copyright 2006 The Apache Software Foundation. - * - * 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 xmltooling/security/XSECCryptoX509CRL.h - * - * Wrapper for X.509 CRL objects, similar to existing XSEC wrappers. - */ - -#if !defined(__xmltooling_x509crl_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_x509crl_h__ - -#include - -#include -#include - -namespace xmltooling { - /** - * Interface class for X.509 CRLs - * The library uses classes derived from this to process X.509 CRLs. - */ - class XMLTOOL_API XSECCryptoX509CRL { - MAKE_NONCOPYABLE(XSECCryptoX509CRL); - protected: - XSECCryptoX509CRL() {} - public: - virtual ~XSECCryptoX509CRL() {} - - /** - * Returns a string that identifies the crypto owner of this library. - * - * @return the crypto provider name - */ - virtual const XMLCh* getProviderName() const=0; - - /** - * Load a CRL into the object. - * Takes a base64 DER-encoded CRL and loads it. - * - * @param buf buffer containing the Base64 encoded CRL - * @param len number of bytes of data in the CRL buffer - */ - - /** - * Returns a duplicate of the original object. - * - * @return the duplicate - */ - virtual XSECCryptoX509CRL* clone() const=0; - - virtual void loadX509CRLBase64Bin(const char* buf, unsigned int len)=0; - - /** - * Load a PEM encoded CRL into the object. - * - * Takes a PEM encoded CRL and loads it. - * - * @param buf buffer containing the PEM encoded CRL - * @param len number of bytes of data in the CRL buffer (0 if the string is null terminated) - */ - void loadX509CRLPEM(const char* buf, unsigned int len=0); - - /** - * Get a Base64 DER encoded copy of the CRL - * - * @return A safeBuffer containing the DER encoded certificate - */ - virtual safeBuffer& getDEREncodingSB(void)=0; - }; -}; - -#endif /* __xmltooling_x509crl_h__ */ - - +/* + * Copyright 2006 The Apache Software Foundation. + * + * 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 xmltooling/security/XSECCryptoX509CRL.h + * + * Wrapper for X.509 CRL objects, similar to existing XSEC wrappers. + */ + +#if !defined(__xmltooling_x509crl_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_x509crl_h__ + +#include + +#include +#include + +namespace xmltooling { + /** + * Interface class for X.509 CRLs + * The library uses classes derived from this to process X.509 CRLs. + */ + class XMLTOOL_API XSECCryptoX509CRL { + MAKE_NONCOPYABLE(XSECCryptoX509CRL); + protected: + XSECCryptoX509CRL() {} + public: + virtual ~XSECCryptoX509CRL() {} + + /** + * Returns a string that identifies the crypto owner of this library. + * + * @return the crypto provider name + */ + virtual const XMLCh* getProviderName() const=0; + + /** + * Load a CRL into the object. + * Takes a base64 DER-encoded CRL and loads it. + * + * @param buf buffer containing the Base64 encoded CRL + * @param len number of bytes of data in the CRL buffer + */ + + /** + * Returns a duplicate of the original object. + * + * @return the duplicate + */ + virtual XSECCryptoX509CRL* clone() const=0; + + virtual void loadX509CRLBase64Bin(const char* buf, unsigned int len)=0; + + /** + * Load a PEM encoded CRL into the object. + * + * Takes a PEM encoded CRL and loads it. + * + * @param buf buffer containing the PEM encoded CRL + * @param len number of bytes of data in the CRL buffer (0 if the string is null terminated) + */ + void loadX509CRLPEM(const char* buf, unsigned int len=0); + + /** + * Get a Base64 DER encoded copy of the CRL + * + * @return A safeBuffer containing the DER encoded certificate + */ + virtual safeBuffer& getDEREncodingSB(void)=0; + }; +}; + +#endif /* __xmltooling_x509crl_h__ */ + + diff --git a/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp b/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp index 4d1eeb2..f64cf12 100644 --- a/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp +++ b/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp @@ -1,157 +1,157 @@ -/* - * Copyright 2001-2005 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. - */ - -/** - * ExplicitKeyTrustEngine.cpp - * - * TrustEngine based on explicit knowledge of peer key information. - */ - -#include "internal.h" -#include "security/X509TrustEngine.h" -#include "signature/SignatureValidator.h" -#include "util/NDC.h" - -#include -#include -#include - -using namespace xmlsignature; -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -namespace xmltooling { - class XMLTOOL_DLLLOCAL ExplicitKeyTrustEngine : public X509TrustEngine - { - public: - ExplicitKeyTrustEngine(const DOMElement* e) : X509TrustEngine(e) {} - virtual ~ExplicitKeyTrustEngine() {} - - virtual bool validate( - Signature& sig, - TrustEngine::KeyInfoIterator& keyInfoSource, - const KeyResolver* keyResolver=NULL - ) const; - virtual bool validate( - XSECCryptoX509* certEE, - const vector& certChain, - TrustEngine::KeyInfoIterator& keyInfoSource, - bool checkName=true, - const KeyResolver* keyResolver=NULL - ) const; - }; - - TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e) - { - return new ExplicitKeyTrustEngine(e); - } -}; - -bool ExplicitKeyTrustEngine::validate( - Signature& sig, - TrustEngine::KeyInfoIterator& keyInfoSource, - const KeyResolver* keyResolver - ) const -{ -#ifdef _DEBUG - NDC ndc("validate"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine"); - - if (!keyInfoSource.hasNext()) { - log.warn("unable to validate signature, no key information available for peer"); - return false; - } - - log.debug("attempting to validate signature with the key information for peer"); - SignatureValidator sigValidator; - while (keyInfoSource.hasNext()) { - XSECCryptoKey* key = (keyResolver ? keyResolver : m_keyResolver)->resolveKey(keyInfoSource.next()); - if (key) { - log.debug("attempting to validate signature with public key..."); - try { - sigValidator.setKey(key); // key now owned by validator - sigValidator.validate(&sig); - log.info("signature validated with public key"); - return true; - } - catch (ValidationException& e) { - if (log.isDebugEnabled()) { - log.debug("public key did not validate signature: %s", e.what()); - } - } - } - else { - log.debug("key information does not resolve to a public key, skipping it"); - } - } - - log.error("no peer key information validated the signature"); - return false; -} - -bool ExplicitKeyTrustEngine::validate( - XSECCryptoX509* certEE, - const vector& certChain, - TrustEngine::KeyInfoIterator& keyInfoSource, - bool checkName, - const KeyResolver* keyResolver - ) const -{ -#ifdef _DEBUG - NDC ndc("validate"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine"); - - if (!certEE) { - log.error("unable to validate, end-entity certificate was null"); - return false; - } - else if (certEE->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { - log.error("only the OpenSSL XSEC provider is supported"); - return false; - } - else if (!keyInfoSource.hasNext()) { - log.warn("unable to validate, no key information available for peer"); - return false; - } - - // The new "basic" trust implementation relies solely on certificates living within the - // role interface to verify the EE certificate. - - log.debug("attempting to match key information from peer with end-entity certificate"); - while (keyInfoSource.hasNext()) { - KeyResolver::ResolvedCertificates resolvedCerts; - if (0 == (keyResolver ? keyResolver : m_keyResolver)->resolveCertificates(keyInfoSource.next(),resolvedCerts)) { - log.debug("key information does not resolve to a certificate, skipping it"); - continue; - } - - log.debug("checking if certificates contained within key information match end-entity certificate"); - if (resolvedCerts.v().front()->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { - log.error("only the OpenSSL XSEC provider is supported"); - continue; - } - else if (!X509_cmp(static_cast(certEE)->getOpenSSLX509(),static_cast(resolvedCerts.v().front())->getOpenSSLX509())) { - log.info("end-entity certificate matches certificate from peer key information"); - return true; - } - } - - log.debug("no certificates within this peer's key information matched the given end-entity certificate"); - return false; -} +/* + * Copyright 2001-2005 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. + */ + +/** + * ExplicitKeyTrustEngine.cpp + * + * TrustEngine based on explicit knowledge of peer key information. + */ + +#include "internal.h" +#include "security/X509TrustEngine.h" +#include "signature/SignatureValidator.h" +#include "util/NDC.h" + +#include +#include +#include + +using namespace xmlsignature; +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +namespace xmltooling { + class XMLTOOL_DLLLOCAL ExplicitKeyTrustEngine : public X509TrustEngine + { + public: + ExplicitKeyTrustEngine(const DOMElement* e) : X509TrustEngine(e) {} + virtual ~ExplicitKeyTrustEngine() {} + + virtual bool validate( + Signature& sig, + TrustEngine::KeyInfoIterator& keyInfoSource, + const KeyResolver* keyResolver=NULL + ) const; + virtual bool validate( + XSECCryptoX509* certEE, + const vector& certChain, + TrustEngine::KeyInfoIterator& keyInfoSource, + bool checkName=true, + const KeyResolver* keyResolver=NULL + ) const; + }; + + TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e) + { + return new ExplicitKeyTrustEngine(e); + } +}; + +bool ExplicitKeyTrustEngine::validate( + Signature& sig, + TrustEngine::KeyInfoIterator& keyInfoSource, + const KeyResolver* keyResolver + ) const +{ +#ifdef _DEBUG + NDC ndc("validate"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine"); + + if (!keyInfoSource.hasNext()) { + log.warn("unable to validate signature, no key information available for peer"); + return false; + } + + log.debug("attempting to validate signature with the key information for peer"); + SignatureValidator sigValidator; + while (keyInfoSource.hasNext()) { + XSECCryptoKey* key = (keyResolver ? keyResolver : m_keyResolver)->resolveKey(keyInfoSource.next()); + if (key) { + log.debug("attempting to validate signature with public key..."); + try { + sigValidator.setKey(key); // key now owned by validator + sigValidator.validate(&sig); + log.info("signature validated with public key"); + return true; + } + catch (ValidationException& e) { + if (log.isDebugEnabled()) { + log.debug("public key did not validate signature: %s", e.what()); + } + } + } + else { + log.debug("key information does not resolve to a public key, skipping it"); + } + } + + log.error("no peer key information validated the signature"); + return false; +} + +bool ExplicitKeyTrustEngine::validate( + XSECCryptoX509* certEE, + const vector& certChain, + TrustEngine::KeyInfoIterator& keyInfoSource, + bool checkName, + const KeyResolver* keyResolver + ) const +{ +#ifdef _DEBUG + NDC ndc("validate"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine"); + + if (!certEE) { + log.error("unable to validate, end-entity certificate was null"); + return false; + } + else if (certEE->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { + log.error("only the OpenSSL XSEC provider is supported"); + return false; + } + else if (!keyInfoSource.hasNext()) { + log.warn("unable to validate, no key information available for peer"); + return false; + } + + // The new "basic" trust implementation relies solely on certificates living within the + // role interface to verify the EE certificate. + + log.debug("attempting to match key information from peer with end-entity certificate"); + while (keyInfoSource.hasNext()) { + KeyResolver::ResolvedCertificates resolvedCerts; + if (0 == (keyResolver ? keyResolver : m_keyResolver)->resolveCertificates(keyInfoSource.next(),resolvedCerts)) { + log.debug("key information does not resolve to a certificate, skipping it"); + continue; + } + + log.debug("checking if certificates contained within key information match end-entity certificate"); + if (resolvedCerts.v().front()->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { + log.error("only the OpenSSL XSEC provider is supported"); + continue; + } + else if (!X509_cmp(static_cast(certEE)->getOpenSSLX509(),static_cast(resolvedCerts.v().front())->getOpenSSLX509())) { + log.info("end-entity certificate matches certificate from peer key information"); + return true; + } + } + + log.debug("no certificates within this peer's key information matched the given end-entity certificate"); + return false; +} diff --git a/xmltooling/security/impl/OpenSSLCryptoX509CRL.cpp b/xmltooling/security/impl/OpenSSLCryptoX509CRL.cpp index 245f76b..74dfd3e 100644 --- a/xmltooling/security/impl/OpenSSLCryptoX509CRL.cpp +++ b/xmltooling/security/impl/OpenSSLCryptoX509CRL.cpp @@ -1,112 +1,112 @@ -/* - * Copyright 2006 The Apache Software Foundation. - * - * 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. - */ - -/** - * OpenSSLCryptoX509CRL.cpp - * - * OpenSSL-based class for handling X.509 CRLs - */ - -#include "internal.h" -#include "security/OpenSSLCryptoX509CRL.h" - -#include -#include -#include - -#include - -XSEC_USING_XERCES(ArrayJanitor); -XSEC_USING_XERCES(Janitor); - -using namespace xmltooling; - -OpenSSLCryptoX509CRL::~OpenSSLCryptoX509CRL() -{ - if (mp_X509CRL) - X509_CRL_free(mp_X509CRL); -} - -OpenSSLCryptoX509CRL::OpenSSLCryptoX509CRL(X509_CRL* x) { - - // Build this from an existing X509_CRL structure - - mp_X509CRL = X509_CRL_dup(x); - - // Now need to create the DER encoding - - BIO* b64 = BIO_new(BIO_f_base64()); - BIO* bmem = BIO_new(BIO_s_mem()); - - BIO_set_mem_eof_return(bmem, 0); - b64 = BIO_push(b64, bmem); - - // Translate X509 to Base64 - - i2d_X509_CRL_bio(b64, x); - - BIO_flush(b64); - - char buf[1024]; - unsigned int l; - - m_DERX509CRL.sbStrcpyIn(""); - - while ((l = BIO_read(bmem, buf, 1023)) > 0) { - buf[l] = '\0'; - m_DERX509CRL.sbStrcatIn(buf); - } - - BIO_free_all(b64); -} - -void OpenSSLCryptoX509CRL::loadX509CRLBase64Bin(const char* buf, unsigned int len) { - - // Free anything currently held. - - if (mp_X509CRL) - X509_CRL_free(mp_X509CRL); - - int bufLen = len; - unsigned char* outBuf; - XSECnew(outBuf, unsigned char[len + 1]); - ArrayJanitor j_outBuf(outBuf); - - XSCryptCryptoBase64 *b64; - XSECnew(b64, XSCryptCryptoBase64); - Janitor j_b64(b64); - - b64->decodeInit(); - bufLen = b64->decode((unsigned char *) buf, len, outBuf, len); - bufLen += b64->decodeFinish(&outBuf[bufLen], len-bufLen); - - if (bufLen > 0) { -#if defined(XSEC_OPENSSL_D2IX509_CONST_BUFFER) - mp_X509CRL= d2i_X509_CRL(NULL, (const unsigned char **) (&outBuf), bufLen); -#else - mp_X509CRL= d2i_X509_CRL(NULL, &outBuf, bufLen); -#endif - } - - // Check to see if we have a CRL.... - if (mp_X509CRL == NULL) { - throw XSECCryptoException(XSECCryptoException::X509Error, - "OpenSSL:X509CRL - Error translating Base64 DER encoding into OpenSSL X509 CRL structure"); - } - - m_DERX509CRL.sbStrcpyIn(buf); - -} +/* + * Copyright 2006 The Apache Software Foundation. + * + * 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. + */ + +/** + * OpenSSLCryptoX509CRL.cpp + * + * OpenSSL-based class for handling X.509 CRLs + */ + +#include "internal.h" +#include "security/OpenSSLCryptoX509CRL.h" + +#include +#include +#include + +#include + +XSEC_USING_XERCES(ArrayJanitor); +XSEC_USING_XERCES(Janitor); + +using namespace xmltooling; + +OpenSSLCryptoX509CRL::~OpenSSLCryptoX509CRL() +{ + if (mp_X509CRL) + X509_CRL_free(mp_X509CRL); +} + +OpenSSLCryptoX509CRL::OpenSSLCryptoX509CRL(X509_CRL* x) { + + // Build this from an existing X509_CRL structure + + mp_X509CRL = X509_CRL_dup(x); + + // Now need to create the DER encoding + + BIO* b64 = BIO_new(BIO_f_base64()); + BIO* bmem = BIO_new(BIO_s_mem()); + + BIO_set_mem_eof_return(bmem, 0); + b64 = BIO_push(b64, bmem); + + // Translate X509 to Base64 + + i2d_X509_CRL_bio(b64, x); + + BIO_flush(b64); + + char buf[1024]; + unsigned int l; + + m_DERX509CRL.sbStrcpyIn(""); + + while ((l = BIO_read(bmem, buf, 1023)) > 0) { + buf[l] = '\0'; + m_DERX509CRL.sbStrcatIn(buf); + } + + BIO_free_all(b64); +} + +void OpenSSLCryptoX509CRL::loadX509CRLBase64Bin(const char* buf, unsigned int len) { + + // Free anything currently held. + + if (mp_X509CRL) + X509_CRL_free(mp_X509CRL); + + int bufLen = len; + unsigned char* outBuf; + XSECnew(outBuf, unsigned char[len + 1]); + ArrayJanitor j_outBuf(outBuf); + + XSCryptCryptoBase64 *b64; + XSECnew(b64, XSCryptCryptoBase64); + Janitor j_b64(b64); + + b64->decodeInit(); + bufLen = b64->decode((unsigned char *) buf, len, outBuf, len); + bufLen += b64->decodeFinish(&outBuf[bufLen], len-bufLen); + + if (bufLen > 0) { +#if defined(XSEC_OPENSSL_D2IX509_CONST_BUFFER) + mp_X509CRL= d2i_X509_CRL(NULL, (const unsigned char **) (&outBuf), bufLen); +#else + mp_X509CRL= d2i_X509_CRL(NULL, &outBuf, bufLen); +#endif + } + + // Check to see if we have a CRL.... + if (mp_X509CRL == NULL) { + throw XSECCryptoException(XSECCryptoException::X509Error, + "OpenSSL:X509CRL - Error translating Base64 DER encoding into OpenSSL X509 CRL structure"); + } + + m_DERX509CRL.sbStrcpyIn(buf); + +} diff --git a/xmltooling/security/impl/XSECCryptoX509CRL.cpp b/xmltooling/security/impl/XSECCryptoX509CRL.cpp index 0c8eea8..e009f58 100644 --- a/xmltooling/security/impl/XSECCryptoX509CRL.cpp +++ b/xmltooling/security/impl/XSECCryptoX509CRL.cpp @@ -1,86 +1,86 @@ -/* - * Copyright 2006 The Apache Software Foundation. - * - * 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. - */ - -/** - * XSECCryptoX509CRL.cpp - * - * Wrapper for X.509 CRL objects, similar to existing XSEC wrappers. - */ - -#include "internal.h" -#include "security/XSECCryptoX509CRL.h" - -#include -#include - -using namespace xmltooling; - -void XSECCryptoX509CRL::loadX509CRLPEM(const char* buf, unsigned int len) -{ - const char * b; - char * b1 = NULL; - if (len == 0) - b = buf; - else { - XSECnew(b1, char[len+1]); - memcpy(b1, buf, len); - b1[len] = '\0'; - b = b1; - } - - const char *p = strstr(buf, "-----BEGIN X509 CRL-----"); - - if (p == NULL) { - - if (b1 != NULL) - delete[] b1; - - throw XSECCryptoException(XSECCryptoException::X509Error, - "X509CRL::loadX509CRLPEM - Cannot find start of PEM CRL"); - - } - - p += strlen("-----BEGIN X509 CRL-----"); - - while (*p == '\n' || *p == '\r' || *p == '-') - p++; - - safeBuffer output; - int i = 0; - while (*p != '\0' && *p != '-') { - output[i++] = *p; - ++p; - } - - if (strstr(p, "-----END X509 CRL-----") != p) { - - if (b1 != NULL) - delete[] b1; - - throw XSECCryptoException(XSECCryptoException::X509Error, - "X509CRL::loadX509PEMCRL - Cannot find end of PEM certificate"); - - } - - if (b1 != NULL) - delete[] b1; - - output[i] = '\0'; - - this->loadX509CRLBase64Bin(output.rawCharBuffer(), i); - -} - +/* + * Copyright 2006 The Apache Software Foundation. + * + * 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. + */ + +/** + * XSECCryptoX509CRL.cpp + * + * Wrapper for X.509 CRL objects, similar to existing XSEC wrappers. + */ + +#include "internal.h" +#include "security/XSECCryptoX509CRL.h" + +#include +#include + +using namespace xmltooling; + +void XSECCryptoX509CRL::loadX509CRLPEM(const char* buf, unsigned int len) +{ + const char * b; + char * b1 = NULL; + if (len == 0) + b = buf; + else { + XSECnew(b1, char[len+1]); + memcpy(b1, buf, len); + b1[len] = '\0'; + b = b1; + } + + const char *p = strstr(buf, "-----BEGIN X509 CRL-----"); + + if (p == NULL) { + + if (b1 != NULL) + delete[] b1; + + throw XSECCryptoException(XSECCryptoException::X509Error, + "X509CRL::loadX509CRLPEM - Cannot find start of PEM CRL"); + + } + + p += strlen("-----BEGIN X509 CRL-----"); + + while (*p == '\n' || *p == '\r' || *p == '-') + p++; + + safeBuffer output; + int i = 0; + while (*p != '\0' && *p != '-') { + output[i++] = *p; + ++p; + } + + if (strstr(p, "-----END X509 CRL-----") != p) { + + if (b1 != NULL) + delete[] b1; + + throw XSECCryptoException(XSECCryptoException::X509Error, + "X509CRL::loadX509PEMCRL - Cannot find end of PEM certificate"); + + } + + if (b1 != NULL) + delete[] b1; + + output[i] = '\0'; + + this->loadX509CRLBase64Bin(output.rawCharBuffer(), i); + +} + diff --git a/xmltooling/signature/CachingKeyResolver.h b/xmltooling/signature/CachingKeyResolver.h index 361a397..dec9b02 100644 --- a/xmltooling/signature/CachingKeyResolver.h +++ b/xmltooling/signature/CachingKeyResolver.h @@ -1,45 +1,45 @@ -/* - * 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 xmltooling/signature/CachingKeyResolver.h - * - * A KeyResolver that caches content across method calls. - */ - -#if !defined(__xmltooling_cachekeyres_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_cachekeyres_h__ - -#include - -namespace xmlsignature { - - /** - * An API for resolving encrypted decryption keys. - */ - class XMLTOOL_API CachingKeyResolver : public xmlsignature::KeyResolver { - public: - virtual ~CachingKeyResolver() {} - - /** - * Clears any cache state. - */ - virtual void clearCache()=0; - }; - -}; - -#endif /* __xmltooling_cachekeyres_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 xmltooling/signature/CachingKeyResolver.h + * + * A KeyResolver that caches content across method calls. + */ + +#if !defined(__xmltooling_cachekeyres_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_cachekeyres_h__ + +#include + +namespace xmlsignature { + + /** + * An API for resolving encrypted decryption keys. + */ + class XMLTOOL_API CachingKeyResolver : public xmlsignature::KeyResolver { + public: + virtual ~CachingKeyResolver() {} + + /** + * Clears any cache state. + */ + virtual void clearCache()=0; + }; + +}; + +#endif /* __xmltooling_cachekeyres_h__ */ diff --git a/xmltooling/signature/ContentReference.h b/xmltooling/signature/ContentReference.h index 672dbea..6a83175 100644 --- a/xmltooling/signature/ContentReference.h +++ b/xmltooling/signature/ContentReference.h @@ -1,62 +1,62 @@ -/* - * 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 ContentReference.h - * - * Interface for creating signature references - */ - -#if !defined(__xmltooling_sigref_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_sigref_h__ - -#include -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmlsignature { - - /** - * Interface for creating signature references based on application requirements. - */ - class XMLTOOL_API ContentReference - { - MAKE_NONCOPYABLE(ContentReference); - public: - virtual ~ContentReference() {} - - /** - * Given a native signature, asks the object to create the reference(s). - * - * @param sig native signature interface - */ - virtual void createReferences(DSIGSignature* sig)=0; - - protected: - ContentReference() {} - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_sigref_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 ContentReference.h + * + * Interface for creating signature references + */ + +#if !defined(__xmltooling_sigref_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_sigref_h__ + +#include +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmlsignature { + + /** + * Interface for creating signature references based on application requirements. + */ + class XMLTOOL_API ContentReference + { + MAKE_NONCOPYABLE(ContentReference); + public: + virtual ~ContentReference() {} + + /** + * Given a native signature, asks the object to create the reference(s). + * + * @param sig native signature interface + */ + virtual void createReferences(DSIGSignature* sig)=0; + + protected: + ContentReference() {} + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_sigref_h__ */ diff --git a/xmltooling/signature/CredentialResolver.h b/xmltooling/signature/CredentialResolver.h index f955f37..cb42fc8 100644 --- a/xmltooling/signature/CredentialResolver.h +++ b/xmltooling/signature/CredentialResolver.h @@ -1,72 +1,72 @@ -/* - * 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 xmltooling/signature/CredentialResolver.h - * - * Resolves keys and certificates "owned" by an entity - */ - -#if !defined(__xmltooling_credres_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_credres_h__ - -#include - -#include -#include -#include - -namespace xmlsignature { - - /** - * An API for resolving local/owned keys and certificates - */ - class XMLTOOL_API CredentialResolver : public xmltooling::Lockable - { - MAKE_NONCOPYABLE(CredentialResolver); - protected: - CredentialResolver() {} - - public: - virtual ~CredentialResolver() {} - - /** - * Returns a secret or private key to use for signing operations. - * The caller is responsible for deleting the key when finished with it. - * - * @return a secret or private key - */ - virtual XSECCryptoKey* getKey() const=0; - - /** - * Returns a set of certificates to publish during signing operations. - * The certificates must be cloned if kept beyond the scope of a lock. - * - * @return a set of certificates - */ - virtual const std::vector& getCertificates() const=0; - }; - - /** - * Registers CredentialResolver classes into the runtime. - */ - void XMLTOOL_API registerCredentialResolvers(); - - /** CredentialResolver based on local files */ - #define FILESYSTEM_CREDENTIAL_RESOLVER "org.opensaml.xmlooling.FilesystemCredentialResolver" -}; - -#endif /* __xmltooling_credres_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 xmltooling/signature/CredentialResolver.h + * + * Resolves keys and certificates "owned" by an entity + */ + +#if !defined(__xmltooling_credres_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_credres_h__ + +#include + +#include +#include +#include + +namespace xmlsignature { + + /** + * An API for resolving local/owned keys and certificates + */ + class XMLTOOL_API CredentialResolver : public xmltooling::Lockable + { + MAKE_NONCOPYABLE(CredentialResolver); + protected: + CredentialResolver() {} + + public: + virtual ~CredentialResolver() {} + + /** + * Returns a secret or private key to use for signing operations. + * The caller is responsible for deleting the key when finished with it. + * + * @return a secret or private key + */ + virtual XSECCryptoKey* getKey() const=0; + + /** + * Returns a set of certificates to publish during signing operations. + * The certificates must be cloned if kept beyond the scope of a lock. + * + * @return a set of certificates + */ + virtual const std::vector& getCertificates() const=0; + }; + + /** + * Registers CredentialResolver classes into the runtime. + */ + void XMLTOOL_API registerCredentialResolvers(); + + /** CredentialResolver based on local files */ + #define FILESYSTEM_CREDENTIAL_RESOLVER "org.opensaml.xmlooling.FilesystemCredentialResolver" +}; + +#endif /* __xmltooling_credres_h__ */ diff --git a/xmltooling/signature/KeyResolver.h b/xmltooling/signature/KeyResolver.h index 9270b1f..2e04dc4 100644 --- a/xmltooling/signature/KeyResolver.h +++ b/xmltooling/signature/KeyResolver.h @@ -1,211 +1,211 @@ -/* - * 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 KeyResolver.h - * - * Resolves public keys and certificates based on KeyInfo information or - * external factors. - */ - -#if !defined(__xmltooling_keyres_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_keyres_h__ - -#include - -#include -#include -#include - -#include -#include - -namespace xmlsignature { - class XMLTOOL_API KeyInfo; - class XMLTOOL_API Signature; - - /** - * An API for resolving keys. The default/simple implementation - * allows a hard-wired key to be supplied. This is mostly - * useful for testing, or to adapt another mechanism for supplying - * keys to this interface. - */ - class XMLTOOL_API KeyResolver { - MAKE_NONCOPYABLE(KeyResolver); - public: - /** - * Constructor based on a single externally supplied key. - * The key will be destroyed when the resolver is. - * - * @param key external key - */ - KeyResolver(XSECCryptoKey* key=NULL) : m_key(key) {} - - virtual ~KeyResolver() { - delete m_key; - } - - /** - * Returns a key based on the supplied KeyInfo information. - * The caller must delete the key when done with it. - * - * @param keyInfo the key information - * @return the resolved key - */ - virtual XSECCryptoKey* resolveKey(const KeyInfo* keyInfo) const { - return m_key ? m_key->clone() : NULL; - } - - /** - * Returns a key based on the supplied KeyInfo information. - * The caller must delete the key when done with it. - * - * @param keyInfo the key information - * @return the resolved key - */ - virtual XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo) const { - return m_key ? m_key->clone() : NULL; - } - - /** - * Returns a key based on the supplied KeyInfo information. - * The caller must delete the key when done with it. - * - * @param sig signature containing the key information - * @return the resolved key - */ - XSECCryptoKey* resolveKey(const Signature* sig) const; - - /** - * A wrapper that handles disposal of certificates when required. - */ - class XMLTOOL_API ResolvedCertificates { - MAKE_NONCOPYABLE(ResolvedCertificates); - bool m_owned; - std::vector m_certs; - public: - ResolvedCertificates() : m_owned(false) {} - ~ResolvedCertificates() { - if (m_owned) { - std::for_each(m_certs.begin(), m_certs.end(), xmltooling::cleanup()); - } - } - const std::vector& v() const { - return m_certs; - } - friend class XMLTOOL_API KeyResolver; - }; - - /** - * Returns a set of certificates based on the supplied KeyInfo information. - * The certificates must be cloned if kept beyond the lifetime of the KeyInfo source. - * - * @param keyInfo the key information - * @param certs reference to object to hold certificates - * @return number of certificates returned - */ - virtual std::vector::size_type resolveCertificates( - const KeyInfo* keyInfo, ResolvedCertificates& certs - ) const; - - /** - * Returns a set of certificates based on the supplied KeyInfo information. - * The certificates must be cloned if kept beyond the lifetime of the KeyInfo source. - * - * @param keyInfo the key information - * @param certs reference to object to hold certificates - * @return number of certificates returned - */ - virtual std::vector::size_type resolveCertificates( - DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs - ) const; - - /** - * Returns a set of certificates based on the supplied KeyInfo information. - * The certificates must be cloned if kept beyond the lifetime of the KeyInfo source. - * - * @param sig signature containing the key information - * @param certs reference to object to hold certificates - * @return number of certificates returned - */ - std::vector::size_type resolveCertificates( - const Signature* sig, ResolvedCertificates& certs - ) const; - - /** - * Returns a CRL based on the supplied KeyInfo information. - * The caller must delete the CRL when done with it. - * - * @param keyInfo the key information - * @return the resolved CRL - */ - virtual xmltooling::XSECCryptoX509CRL* resolveCRL(const KeyInfo* keyInfo) const; - - /** - * Returns a CRL based on the supplied KeyInfo information. - * The caller must delete the CRL when done with it. - * - * @param keyInfo the key information - * @return the resolved CRL - */ - virtual xmltooling::XSECCryptoX509CRL* resolveCRL(DSIGKeyInfoList* keyInfo) const; - - /** - * Returns a CRL based on the supplied KeyInfo information. - * The caller must delete the CRL when done with it. - * - * @param sig signature containing the key information - * @return the resolved CRL - */ - xmltooling::XSECCryptoX509CRL* resolveCRL(const Signature* sig) const; - - protected: - XSECCryptoKey* m_key; - - /** - * Accessor for certificate vector from derived KeyResolver classes. - * - * @param certs certificate wrapper to access - * @return modifiable reference to vector inside wrapper - */ - std::vector& accessCertificates(ResolvedCertificates& certs) const { - return certs.m_certs; - } - - /** - * Accessor for certificate ownership flag from derived KeyResolver classes. - * - * @param certs certificate wrapper to access - * @return modifiable reference to ownership flag inside wrapper - */ - bool& accessOwned(ResolvedCertificates& certs) const { - return certs.m_owned; - } - }; - - /** - * Registers KeyResolver classes into the runtime. - */ - void XMLTOOL_API registerKeyResolvers(); - - /** KeyResolver based on hard-wired key */ - #define FILESYSTEM_KEY_RESOLVER "org.opensaml.xmlooling.FilesystemKeyResolver" - - /** KeyResolver based on extracting information directly out of a KeyInfo */ - #define INLINE_KEY_RESOLVER "org.opensaml.xmlooling.InlineKeyResolver" -}; - -#endif /* __xmltooling_keyres_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 KeyResolver.h + * + * Resolves public keys and certificates based on KeyInfo information or + * external factors. + */ + +#if !defined(__xmltooling_keyres_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_keyres_h__ + +#include + +#include +#include +#include + +#include +#include + +namespace xmlsignature { + class XMLTOOL_API KeyInfo; + class XMLTOOL_API Signature; + + /** + * An API for resolving keys. The default/simple implementation + * allows a hard-wired key to be supplied. This is mostly + * useful for testing, or to adapt another mechanism for supplying + * keys to this interface. + */ + class XMLTOOL_API KeyResolver { + MAKE_NONCOPYABLE(KeyResolver); + public: + /** + * Constructor based on a single externally supplied key. + * The key will be destroyed when the resolver is. + * + * @param key external key + */ + KeyResolver(XSECCryptoKey* key=NULL) : m_key(key) {} + + virtual ~KeyResolver() { + delete m_key; + } + + /** + * Returns a key based on the supplied KeyInfo information. + * The caller must delete the key when done with it. + * + * @param keyInfo the key information + * @return the resolved key + */ + virtual XSECCryptoKey* resolveKey(const KeyInfo* keyInfo) const { + return m_key ? m_key->clone() : NULL; + } + + /** + * Returns a key based on the supplied KeyInfo information. + * The caller must delete the key when done with it. + * + * @param keyInfo the key information + * @return the resolved key + */ + virtual XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo) const { + return m_key ? m_key->clone() : NULL; + } + + /** + * Returns a key based on the supplied KeyInfo information. + * The caller must delete the key when done with it. + * + * @param sig signature containing the key information + * @return the resolved key + */ + XSECCryptoKey* resolveKey(const Signature* sig) const; + + /** + * A wrapper that handles disposal of certificates when required. + */ + class XMLTOOL_API ResolvedCertificates { + MAKE_NONCOPYABLE(ResolvedCertificates); + bool m_owned; + std::vector m_certs; + public: + ResolvedCertificates() : m_owned(false) {} + ~ResolvedCertificates() { + if (m_owned) { + std::for_each(m_certs.begin(), m_certs.end(), xmltooling::cleanup()); + } + } + const std::vector& v() const { + return m_certs; + } + friend class XMLTOOL_API KeyResolver; + }; + + /** + * Returns a set of certificates based on the supplied KeyInfo information. + * The certificates must be cloned if kept beyond the lifetime of the KeyInfo source. + * + * @param keyInfo the key information + * @param certs reference to object to hold certificates + * @return number of certificates returned + */ + virtual std::vector::size_type resolveCertificates( + const KeyInfo* keyInfo, ResolvedCertificates& certs + ) const; + + /** + * Returns a set of certificates based on the supplied KeyInfo information. + * The certificates must be cloned if kept beyond the lifetime of the KeyInfo source. + * + * @param keyInfo the key information + * @param certs reference to object to hold certificates + * @return number of certificates returned + */ + virtual std::vector::size_type resolveCertificates( + DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs + ) const; + + /** + * Returns a set of certificates based on the supplied KeyInfo information. + * The certificates must be cloned if kept beyond the lifetime of the KeyInfo source. + * + * @param sig signature containing the key information + * @param certs reference to object to hold certificates + * @return number of certificates returned + */ + std::vector::size_type resolveCertificates( + const Signature* sig, ResolvedCertificates& certs + ) const; + + /** + * Returns a CRL based on the supplied KeyInfo information. + * The caller must delete the CRL when done with it. + * + * @param keyInfo the key information + * @return the resolved CRL + */ + virtual xmltooling::XSECCryptoX509CRL* resolveCRL(const KeyInfo* keyInfo) const; + + /** + * Returns a CRL based on the supplied KeyInfo information. + * The caller must delete the CRL when done with it. + * + * @param keyInfo the key information + * @return the resolved CRL + */ + virtual xmltooling::XSECCryptoX509CRL* resolveCRL(DSIGKeyInfoList* keyInfo) const; + + /** + * Returns a CRL based on the supplied KeyInfo information. + * The caller must delete the CRL when done with it. + * + * @param sig signature containing the key information + * @return the resolved CRL + */ + xmltooling::XSECCryptoX509CRL* resolveCRL(const Signature* sig) const; + + protected: + XSECCryptoKey* m_key; + + /** + * Accessor for certificate vector from derived KeyResolver classes. + * + * @param certs certificate wrapper to access + * @return modifiable reference to vector inside wrapper + */ + std::vector& accessCertificates(ResolvedCertificates& certs) const { + return certs.m_certs; + } + + /** + * Accessor for certificate ownership flag from derived KeyResolver classes. + * + * @param certs certificate wrapper to access + * @return modifiable reference to ownership flag inside wrapper + */ + bool& accessOwned(ResolvedCertificates& certs) const { + return certs.m_owned; + } + }; + + /** + * Registers KeyResolver classes into the runtime. + */ + void XMLTOOL_API registerKeyResolvers(); + + /** KeyResolver based on hard-wired key */ + #define FILESYSTEM_KEY_RESOLVER "org.opensaml.xmlooling.FilesystemKeyResolver" + + /** KeyResolver based on extracting information directly out of a KeyInfo */ + #define INLINE_KEY_RESOLVER "org.opensaml.xmlooling.InlineKeyResolver" +}; + +#endif /* __xmltooling_keyres_h__ */ diff --git a/xmltooling/signature/OpenSSLCredentialResolver.h b/xmltooling/signature/OpenSSLCredentialResolver.h index e119380..77c2b95 100644 --- a/xmltooling/signature/OpenSSLCredentialResolver.h +++ b/xmltooling/signature/OpenSSLCredentialResolver.h @@ -1,54 +1,54 @@ -/* - * 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 xmltooling/signature/OpenSSLCredentialResolver.h - * - * OpenSSL-specific credential resolver - */ - -#if !defined(__xmltooling_opensslcredres_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_opensslcredres_h__ - -#include - -#include - -namespace xmlsignature { - - /** - * An OpenSSL-specific API for resolving local/owned keys and certificates - */ - class XMLTOOL_API OpenSSLCredentialResolver : public CredentialResolver - { - protected: - OpenSSLCredentialResolver() {} - - public: - virtual ~OpenSSLCredentialResolver() {} - - /** - * Attaches credentials to an OpenSSL SSL context object. - * The resolver is unlockable after attachment. - * - * @param ctx an SSL context - */ - virtual void attach(SSL_CTX* ctx) const=0; - }; - -}; - -#endif /* __xmltooling_opensslcredres_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 xmltooling/signature/OpenSSLCredentialResolver.h + * + * OpenSSL-specific credential resolver + */ + +#if !defined(__xmltooling_opensslcredres_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_opensslcredres_h__ + +#include + +#include + +namespace xmlsignature { + + /** + * An OpenSSL-specific API for resolving local/owned keys and certificates + */ + class XMLTOOL_API OpenSSLCredentialResolver : public CredentialResolver + { + protected: + OpenSSLCredentialResolver() {} + + public: + virtual ~OpenSSLCredentialResolver() {} + + /** + * Attaches credentials to an OpenSSL SSL context object. + * The resolver is unlockable after attachment. + * + * @param ctx an SSL context + */ + virtual void attach(SSL_CTX* ctx) const=0; + }; + +}; + +#endif /* __xmltooling_opensslcredres_h__ */ diff --git a/xmltooling/signature/Signature.h b/xmltooling/signature/Signature.h index 6ccc49c..71314ac 100644 --- a/xmltooling/signature/Signature.h +++ b/xmltooling/signature/Signature.h @@ -1,172 +1,172 @@ -/* - * 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 Signature.h - * - * XMLObject representing XML Digital Signature, version 20020212, Signature element. - */ - -#if !defined(__xmltooling_sig_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_sig_h__ - -#include -#include -#include -#include - -#include - -/** - * @namespace xmlsignature - * Public namespace of XML Signature classes - */ -namespace xmlsignature { - - class XMLTOOL_API KeyInfo; - - /** - * XMLObject representing XML Digital Signature, version 20020212, Signature element. - * The default signature settings include Exclusive c14n w/o comments, SHA-1 digests, - * and RSA-SHA1 signing. - */ - class XMLTOOL_API Signature : public virtual xmltooling::XMLObject - { - public: - virtual ~Signature() {} - - /** Element local name */ - static const XMLCh LOCAL_NAME[]; - - /** - * Sets the canonicalization method for the ds:SignedInfo element - * - * @param c14n the canonicalization method - */ - virtual void setCanonicalizationMethod(const XMLCh* c14n)=0; - - /** - * Sets the signing algorithm for the signature. - * - * @param sm the signature algorithm - */ - virtual void setSignatureAlgorithm(const XMLCh* sm)=0; - - /** - * Sets the signing key used to create the signature. - * - * @param signingKey the secret/private key used to create the signature - */ - virtual void setSigningKey(XSECCryptoKey* signingKey)=0; - - /** - * Sets a KeyInfo object to embed in the Signature. - * - * @param keyInfo pointer to a KeyInfo object, or NULL - */ - virtual void setKeyInfo(KeyInfo* keyInfo)=0; - - /** - * Gets the KeyInfo object associated with the Signature. - * This is NOT provided for access to the - * data associated with an unmarshalled signature. It is - * used only in the creation of signatures. Access to data - * for validation purposes is provided through the native - * DSIGSignature object. - * - * @return pointer to a KeyInfo object, or NULL - */ - virtual KeyInfo* getKeyInfo() const=0; - - /** - * Sets the ContentReference object to the Signature to be applied - * when the signature is created. - * - * @param reference the reference to attach, or NULL - */ - virtual void setContentReference(ContentReference* reference)=0; - - /** - * Gets the ContentReference object associated with the Signature. - * This is NOT provided for access to the - * data associated with an unmarshalled signature. It is - * used only in the creation of signatures. Access to data - * for validation purposes is provided through the native - * DSIGSignature object. - * - * @return pointer to a ContentReference object, or NULL - */ - virtual ContentReference* getContentReference() const=0; - - - /** - * Gets the native Apache signature object, if present. - * - * @return the native Apache signature interface - */ - virtual DSIGSignature* getXMLSignature() const=0; - - /** - * Compute and append the signature based on the assigned - * ContentReference, KeyInfo, and signing key. - */ - virtual void sign()=0; - - /** - * Type-safe clone operation. - * - * @return copy of object - */ - virtual Signature* cloneSignature() const=0; - - protected: - Signature() {} - }; - - /** - * Builder for Signature objects. - */ - class XMLTOOL_API SignatureBuilder : public xmltooling::XMLObjectBuilder - { - public: - virtual Signature* buildObject( - const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix=NULL, const xmltooling::QName* schemaType=NULL - ) const; - - /** - * Default builder - * - * @return empty Signature object - */ - virtual Signature* buildObject() const; - - static Signature* buildSignature() { - const SignatureBuilder* b = dynamic_cast( - xmltooling::XMLObjectBuilder::getBuilder( - xmltooling::QName(xmltooling::XMLConstants::XMLSIG_NS,Signature::LOCAL_NAME) - ) - ); - if (b) - return b->buildObject(); - throw xmltooling::XMLObjectException("Unable to obtain typed builder for Signature."); - } - }; - - DECL_XMLTOOLING_EXCEPTION(SignatureException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmlsignature,xmltooling::XMLSecurityException,Exceptions in signature processing); - -}; - -#endif /* __xmltooling_sig_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 Signature.h + * + * XMLObject representing XML Digital Signature, version 20020212, Signature element. + */ + +#if !defined(__xmltooling_sig_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_sig_h__ + +#include +#include +#include +#include + +#include + +/** + * @namespace xmlsignature + * Public namespace of XML Signature classes + */ +namespace xmlsignature { + + class XMLTOOL_API KeyInfo; + + /** + * XMLObject representing XML Digital Signature, version 20020212, Signature element. + * The default signature settings include Exclusive c14n w/o comments, SHA-1 digests, + * and RSA-SHA1 signing. + */ + class XMLTOOL_API Signature : public virtual xmltooling::XMLObject + { + public: + virtual ~Signature() {} + + /** Element local name */ + static const XMLCh LOCAL_NAME[]; + + /** + * Sets the canonicalization method for the ds:SignedInfo element + * + * @param c14n the canonicalization method + */ + virtual void setCanonicalizationMethod(const XMLCh* c14n)=0; + + /** + * Sets the signing algorithm for the signature. + * + * @param sm the signature algorithm + */ + virtual void setSignatureAlgorithm(const XMLCh* sm)=0; + + /** + * Sets the signing key used to create the signature. + * + * @param signingKey the secret/private key used to create the signature + */ + virtual void setSigningKey(XSECCryptoKey* signingKey)=0; + + /** + * Sets a KeyInfo object to embed in the Signature. + * + * @param keyInfo pointer to a KeyInfo object, or NULL + */ + virtual void setKeyInfo(KeyInfo* keyInfo)=0; + + /** + * Gets the KeyInfo object associated with the Signature. + * This is NOT provided for access to the + * data associated with an unmarshalled signature. It is + * used only in the creation of signatures. Access to data + * for validation purposes is provided through the native + * DSIGSignature object. + * + * @return pointer to a KeyInfo object, or NULL + */ + virtual KeyInfo* getKeyInfo() const=0; + + /** + * Sets the ContentReference object to the Signature to be applied + * when the signature is created. + * + * @param reference the reference to attach, or NULL + */ + virtual void setContentReference(ContentReference* reference)=0; + + /** + * Gets the ContentReference object associated with the Signature. + * This is NOT provided for access to the + * data associated with an unmarshalled signature. It is + * used only in the creation of signatures. Access to data + * for validation purposes is provided through the native + * DSIGSignature object. + * + * @return pointer to a ContentReference object, or NULL + */ + virtual ContentReference* getContentReference() const=0; + + + /** + * Gets the native Apache signature object, if present. + * + * @return the native Apache signature interface + */ + virtual DSIGSignature* getXMLSignature() const=0; + + /** + * Compute and append the signature based on the assigned + * ContentReference, KeyInfo, and signing key. + */ + virtual void sign()=0; + + /** + * Type-safe clone operation. + * + * @return copy of object + */ + virtual Signature* cloneSignature() const=0; + + protected: + Signature() {} + }; + + /** + * Builder for Signature objects. + */ + class XMLTOOL_API SignatureBuilder : public xmltooling::XMLObjectBuilder + { + public: + virtual Signature* buildObject( + const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix=NULL, const xmltooling::QName* schemaType=NULL + ) const; + + /** + * Default builder + * + * @return empty Signature object + */ + virtual Signature* buildObject() const; + + static Signature* buildSignature() { + const SignatureBuilder* b = dynamic_cast( + xmltooling::XMLObjectBuilder::getBuilder( + xmltooling::QName(xmltooling::XMLConstants::XMLSIG_NS,Signature::LOCAL_NAME) + ) + ); + if (b) + return b->buildObject(); + throw xmltooling::XMLObjectException("Unable to obtain typed builder for Signature."); + } + }; + + DECL_XMLTOOLING_EXCEPTION(SignatureException,XMLTOOL_EXCEPTIONAPI(XMLTOOL_API),xmlsignature,xmltooling::XMLSecurityException,Exceptions in signature processing); + +}; + +#endif /* __xmltooling_sig_h__ */ diff --git a/xmltooling/signature/SignatureValidator.h b/xmltooling/signature/SignatureValidator.h index 7f7fa7d..5ba231d 100644 --- a/xmltooling/signature/SignatureValidator.h +++ b/xmltooling/signature/SignatureValidator.h @@ -1,94 +1,94 @@ -/* - * 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 SignatureValidator.h - * - * Validator for signatures based on an externally-supplied key - */ - -#if !defined(__xmltooling_sigval_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_sigval_h__ - -#include -#include -#include - -namespace xmlsignature { - - /** - * Validator for signatures based on a Key or a KeyResolver - */ - class XMLTOOL_API SignatureValidator : public xmltooling::Validator - { - public: - /** - * Constructor using a KeyResolver - * - * @param resolver the key resolver to use, will be freed by Validator - */ - SignatureValidator(KeyResolver* resolver) : m_key(NULL), m_resolver(resolver) { - } - - /** - * Constructor using a Key - * - * @param key the verification key to use, will be freed by Validator - */ - SignatureValidator(XSECCryptoKey* key=NULL) : m_key(key), m_resolver(NULL) { - } - - virtual ~SignatureValidator() { - delete m_key; - delete m_resolver; - } - - virtual void validate(const xmltooling::XMLObject* xmlObject) const; - - virtual void validate(const Signature* signature) const; - - /** - * Replace the current Key, if any, with a new one. - * - * @param key the Key to attach - */ - void setKey(XSECCryptoKey* key) { - delete m_key; - delete m_resolver; - m_resolver=NULL; - m_key=key; - } - - /** - * Replace the current KeyResolver, if any, with a new one. - * - * @param resolver the KeyResolver to attach - */ - void setKeyResolver(KeyResolver* resolver) { - delete m_key; - delete m_resolver; - m_key=NULL; - m_resolver=resolver; - } - - protected: - XSECCryptoKey* m_key; - KeyResolver* m_resolver; - }; - -}; - -#endif /* __xmltooling_sigval_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 SignatureValidator.h + * + * Validator for signatures based on an externally-supplied key + */ + +#if !defined(__xmltooling_sigval_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_sigval_h__ + +#include +#include +#include + +namespace xmlsignature { + + /** + * Validator for signatures based on a Key or a KeyResolver + */ + class XMLTOOL_API SignatureValidator : public xmltooling::Validator + { + public: + /** + * Constructor using a KeyResolver + * + * @param resolver the key resolver to use, will be freed by Validator + */ + SignatureValidator(KeyResolver* resolver) : m_key(NULL), m_resolver(resolver) { + } + + /** + * Constructor using a Key + * + * @param key the verification key to use, will be freed by Validator + */ + SignatureValidator(XSECCryptoKey* key=NULL) : m_key(key), m_resolver(NULL) { + } + + virtual ~SignatureValidator() { + delete m_key; + delete m_resolver; + } + + virtual void validate(const xmltooling::XMLObject* xmlObject) const; + + virtual void validate(const Signature* signature) const; + + /** + * Replace the current Key, if any, with a new one. + * + * @param key the Key to attach + */ + void setKey(XSECCryptoKey* key) { + delete m_key; + delete m_resolver; + m_resolver=NULL; + m_key=key; + } + + /** + * Replace the current KeyResolver, if any, with a new one. + * + * @param resolver the KeyResolver to attach + */ + void setKeyResolver(KeyResolver* resolver) { + delete m_key; + delete m_resolver; + m_key=NULL; + m_resolver=resolver; + } + + protected: + XSECCryptoKey* m_key; + KeyResolver* m_resolver; + }; + +}; + +#endif /* __xmltooling_sigval_h__ */ diff --git a/xmltooling/signature/impl/FilesystemCredentialResolver.cpp b/xmltooling/signature/impl/FilesystemCredentialResolver.cpp index 2389c14..f838142 100644 --- a/xmltooling/signature/impl/FilesystemCredentialResolver.cpp +++ b/xmltooling/signature/impl/FilesystemCredentialResolver.cpp @@ -1,574 +1,574 @@ -/* - * Copyright 2001-2005 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. - */ - -/** - * FilesystemCredentialResolver.cpp - * - * Supplies credentials from local files - */ - -#include "internal.h" -#include "signature/KeyResolver.h" -#include "signature/OpenSSLCredentialResolver.h" -#include "util/NDC.h" -#include "util/XMLHelper.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace xmlsignature; -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -// OpenSSL password callback... -static int passwd_callback(char* buf, int len, int verify, void* passwd) -{ - if(!verify) - { - if(passwd && len > strlen(reinterpret_cast(passwd))) - { - strcpy(buf,reinterpret_cast(passwd)); - return strlen(buf); - } - } - return 0; -} - -namespace xmlsignature { - class FilesystemCredentialResolver : public OpenSSLCredentialResolver, public KeyResolver - { - public: - FilesystemCredentialResolver(const DOMElement* e); - virtual ~FilesystemCredentialResolver(); - - Lockable* lock() { return this; } - void unlock() {} - - XSECCryptoKey* loadKey(); - - XSECCryptoKey* getKey() const { return m_key ? m_key->clone() : NULL; } - const vector& getCertificates() const { return m_xseccerts; } - void attach(SSL_CTX* ctx) const; - - XSECCryptoKey* resolveKey(const KeyInfo* keyInfo) const { return m_key ? m_key->clone() : NULL; } - XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo) const { return m_key ? m_key->clone() : NULL; } - vector::size_type resolveCertificates(const KeyInfo* keyInfo, ResolvedCertificates& certs) const { - accessCertificates(certs).assign(m_xseccerts.begin(), m_xseccerts.end()); - accessOwned(certs) = false; - return accessCertificates(certs).size(); - } - vector::size_type resolveCertificates(DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs) const { - accessCertificates(certs).assign(m_xseccerts.begin(), m_xseccerts.end()); - accessOwned(certs) = false; - return accessCertificates(certs).size(); - } - - private: - enum format_t { PEM=SSL_FILETYPE_PEM, DER=SSL_FILETYPE_ASN1, _PKCS12, UNKNOWN }; - - format_t getEncodingFormat(BIO* in) const; - string formatToString(format_t format) const; - format_t xmlFormatToFormat(const XMLCh* format_xml) const; - - format_t m_keyformat; - string m_keypath,m_keypass; - vector m_certs; - vector m_xseccerts; - XSECCryptoKey* m_key; - }; - - CredentialResolver* XMLTOOL_DLLLOCAL FilesystemCredentialResolverFactory(const DOMElement* const & e) - { - return new FilesystemCredentialResolver(e); - } - - KeyResolver* XMLTOOL_DLLLOCAL FilesystemKeyResolverFactory(const DOMElement* const & e) - { - return new FilesystemCredentialResolver(e); - } -}; - -static const XMLCh CAPath[] = UNICODE_LITERAL_6(C,A,P,a,t,h); -static const XMLCh Certificate[] = UNICODE_LITERAL_11(C,e,r,t,i,f,i,c,a,t,e); -static const XMLCh format[] = UNICODE_LITERAL_6(f,o,r,m,a,t); -static const XMLCh Key[] = UNICODE_LITERAL_3(K,e,y); -static const XMLCh password[] = UNICODE_LITERAL_8(p,a,s,s,w,o,r,d); -static const XMLCh Path[] = UNICODE_LITERAL_4(P,a,t,h); - -FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) : m_key(NULL) -{ -#ifdef _DEBUG - NDC ndc("FilesystemCredentialResolver"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".CredentialResolver"); - - format_t fformat; - const XMLCh* format_xml=NULL; - BIO* in = NULL; - - // Move to Key - const DOMElement* root=e; - e=XMLHelper::getFirstChildElement(root,Key); - if (e) { - - // Get raw format attrib value, but defer processing til later since may need to - // determine format dynamically, and we need the Path for that. - format_xml=e->getAttributeNS(NULL,format); - - const XMLCh* password_xml=e->getAttributeNS(NULL,password); - if (password_xml) { - auto_ptr_char kp(password_xml); - m_keypass=kp.get(); - } - - e=XMLHelper::getFirstChildElement(e,Path); - if (e && e->hasChildNodes()) { - const XMLCh* s=e->getFirstChild()->getNodeValue(); - auto_ptr_char kpath(s); -#ifdef WIN32 - struct _stat stat_buf; - if (_stat(kpath.get(), &stat_buf) != 0) -#else - struct stat stat_buf; - if (stat(kpath.get(), &stat_buf) != 0) -#endif - { - log.error("key file (%s) can't be opened", kpath.get()); - throw XMLSecurityException("FilesystemCredentialResolver can't access key file ($1)",params(1,kpath.get())); - } - m_keypath=kpath.get(); - } - else { - log.error("Path element missing inside Key element"); - throw XMLSecurityException("FilesystemCredentialResolver can't access key file, no Path element specified."); - } - - // Determine the key encoding format dynamically, if not explicitly specified - if (format_xml && *format_xml) { - fformat = xmlFormatToFormat(format_xml); - if (fformat != UNKNOWN) { - m_keyformat = fformat; - } - else { - auto_ptr_char unknown(format_xml); - log.error("configuration specifies unknown key encoding format (%s)", unknown.get()); - throw XMLSecurityException("FilesystemCredentialResolver configuration contains unknown key encoding format ($1)",params(1,unknown.get())); - } - } - else { - in=BIO_new(BIO_s_file_internal()); - if (in && BIO_read_filename(in,m_keypath.c_str())>0) { - m_keyformat = getEncodingFormat(in); - log.debug("key encoding format for (%s) dynamically resolved as (%s)", m_keypath.c_str(), formatToString(m_keyformat).c_str()); - } - else { - log.error("key file (%s) can't be read to determine encoding format", m_keypath.c_str()); - throw XMLSecurityException("FilesystemCredentialResolver can't read key file ($1) to determine encoding format",params(1,m_keypath.c_str())); - } - if (in) - BIO_free(in); - in = NULL; - } - - // Load the key. - m_key = loadKey(); - } - - // Check for Certificate - e=XMLHelper::getFirstChildElement(root,Certificate); - if (!e) - return; - auto_ptr_char certpass(e->getAttributeNS(NULL,password)); - - DOMElement* ep=XMLHelper::getFirstChildElement(e,Path); - if (!ep || !ep->hasChildNodes()) { - log.error("Path element missing inside Certificate element or is empty"); - throw XMLSecurityException("FilesystemCredentialResolver can't access certificate file, missing or empty Path element."); - } - - auto_ptr_char certpath(ep->getFirstChild()->getNodeValue()); - format_xml=e->getAttributeNS(NULL,format); - if (format_xml && *format_xml) { - fformat = xmlFormatToFormat(format_xml); - if (fformat == UNKNOWN) { - auto_ptr_char unknown(format_xml); - log.error("configuration specifies unknown certificate encoding format (%s)", unknown.get()); - throw XMLSecurityException("FilesystemCredentialResolver configuration contains unknown certificate encoding format ($1)",params(1,unknown.get())); - } - } - - try { - X509* x=NULL; - PKCS12* p12=NULL; - in=BIO_new(BIO_s_file_internal()); - if (in && BIO_read_filename(in,certpath.get())>0) { - if (!format_xml || !*format_xml) { - // Determine the cert encoding format dynamically, if not explicitly specified - fformat = getEncodingFormat(in); - log.debug("certificate encoding format for (%s) dynamically resolved as (%s)", certpath.get(), formatToString(fformat).c_str()); - } - - switch(fformat) { - case PEM: - while (x=PEM_read_bio_X509(in,NULL,passwd_callback,const_cast(certpass.get()))) - m_certs.push_back(x); - break; - - case DER: - x=d2i_X509_bio(in,NULL); - if (x) - m_certs.push_back(x); - else { - log_openssl(); - BIO_free(in); - throw XMLSecurityException("FilesystemCredentialResolver unable to load DER certificate from file ($1)",params(1,certpath.get())); - } - break; - - case _PKCS12: - p12=d2i_PKCS12_bio(in,NULL); - if (p12) { - PKCS12_parse(p12, certpass.get(), NULL, &x, NULL); - PKCS12_free(p12); - } - if (x) { - m_certs.push_back(x); - x=NULL; - } else { - log_openssl(); - BIO_free(in); - throw XMLSecurityException("FilesystemCredentialResolver unable to load PKCS12 certificate from file ($1)",params(1,certpath.get())); - } - break; - } // end switch - - } else { - log_openssl(); - if (in) { - BIO_free(in); - in=NULL; - } - throw XMLSecurityException("FilesystemCredentialResolver unable to load certificate(s) from file ($1)",params(1,certpath.get())); - } - if (in) { - BIO_free(in); - in=NULL; - } - - if (m_certs.empty()) { - throw XMLSecurityException("FilesystemCredentialResolver unable to load any certificate(s)"); - } - - // Load any extra CA files. - DOMElement* extra=XMLHelper::getFirstChildElement(e,CAPath); - while (extra) { - if (!extra->hasChildNodes()) { - log.warn("skipping empty CAPath element"); - extra = XMLHelper::getNextSiblingElement(extra,CAPath); - continue; - } - auto_ptr_char capath(extra->getFirstChild()->getNodeValue()); - x=NULL; - p12=NULL; - in=BIO_new(BIO_s_file_internal()); - if (in && BIO_read_filename(in,capath.get())>0) { - if (!format_xml || !*format_xml) { - // Determine the cert encoding format dynamically, if not explicitly specified - fformat = getEncodingFormat(in); - log.debug("CA certificate encoding format for (%s) dynamically resolved as (%s)", certpath.get(), formatToString(fformat).c_str()); - } - - switch (fformat) { - case PEM: - while (x=PEM_read_bio_X509(in,NULL,passwd_callback,const_cast(certpass.get()))) - m_certs.push_back(x); - break; - - case DER: - x=d2i_X509_bio(in,NULL); - if (x) - m_certs.push_back(x); - else { - log_openssl(); - BIO_free(in); - throw XMLSecurityException("FilesystemCredentialResolver unable to load DER CA certificate from file ($1)",params(1,capath.get())); - } - break; - - case _PKCS12: - p12 = d2i_PKCS12_bio(in, NULL); - if (p12) { - PKCS12_parse(p12, certpass.get(), NULL, &x, NULL); - PKCS12_free(p12); - } - if (x) { - m_certs.push_back(x); - x=NULL; - } - else { - log_openssl(); - BIO_free(in); - throw XMLSecurityException("FilesystemCredentialResolver unable to load PKCS12 CA certificate from file ($1)",params(1,capath.get())); - } - break; - } //end switch - - BIO_free(in); - } - else { - if (in) - BIO_free(in); - log_openssl(); - log.error("CA file (%s) can't be opened", capath.get()); - throw XMLSecurityException("FilesystemCredentialResolver can't open CA file ($1)",params(1,capath.get())); - } - - extra = XMLHelper::getNextSiblingElement(extra,CAPath); - } - } - catch (XMLToolingException&) { - for (vector::iterator j=m_certs.begin(); j!=m_certs.end(); j++) - X509_free(*j); - throw; - } - - // Reflect certs over to XSEC form. - for (vector::iterator j=m_certs.begin(); j!=m_certs.end(); j++) - m_xseccerts.push_back(new OpenSSLCryptoX509(*j)); -} - -XSECCryptoKey* FilesystemCredentialResolver::loadKey() -{ -#ifdef _DEBUG - NDC ndc("loadKey"); -#endif - - // Get a EVP_PKEY. - EVP_PKEY* pkey=NULL; - BIO* in=BIO_new(BIO_s_file_internal()); - if (in && BIO_read_filename(in,m_keypath.c_str())>0) { - switch (m_keyformat) { - case PEM: - pkey=PEM_read_bio_PrivateKey(in, NULL, passwd_callback, const_cast(m_keypass.c_str())); - break; - - case DER: - pkey=d2i_PrivateKey_bio(in, NULL); - break; - - default: { - PKCS12* p12 = d2i_PKCS12_bio(in, NULL); - if (p12) { - PKCS12_parse(p12, const_cast(m_keypass.c_str()), &pkey, NULL, NULL); - PKCS12_free(p12); - } - } - } - } - if (in) - BIO_free(in); - - // Now map it to an XSEC wrapper. - if (pkey) { - XSECCryptoKey* ret=NULL; - switch (pkey->type) { - case EVP_PKEY_RSA: - ret=new OpenSSLCryptoKeyRSA(pkey); - break; - - case EVP_PKEY_DSA: - ret=new OpenSSLCryptoKeyDSA(pkey); - break; - - default: - Category::getInstance(XMLTOOLING_LOGCAT".CredentialResolver").error("unsupported private key type"); - } - EVP_PKEY_free(pkey); - if (ret) - return ret; - } - - log_openssl(); - throw XMLSecurityException("FilesystemCredentialResolver unable to load private key from file."); -} - -FilesystemCredentialResolver::~FilesystemCredentialResolver() -{ - delete m_key; - for_each(m_certs.begin(),m_certs.end(),X509_free); - for_each(m_xseccerts.begin(),m_xseccerts.end(),xmltooling::cleanup()); -} - -void FilesystemCredentialResolver::attach(SSL_CTX* ctx) const -{ -#ifdef _DEBUG - NDC ndc("attach"); -#endif - - // Attach key. - SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); - SSL_CTX_set_default_passwd_cb_userdata(ctx, const_cast(m_keypass.c_str())); - - int ret=0; - switch (m_keyformat) { - case PEM: - ret=SSL_CTX_use_PrivateKey_file(ctx, m_keypath.c_str(), m_keyformat); - break; - - case DER: - ret=SSL_CTX_use_RSAPrivateKey_file(ctx, m_keypath.c_str(), m_keyformat); - break; - - default: { - BIO* in=BIO_new(BIO_s_file_internal()); - if (in && BIO_read_filename(in,m_keypath.c_str())>0) { - EVP_PKEY* pkey=NULL; - PKCS12* p12 = d2i_PKCS12_bio(in, NULL); - if (p12) { - PKCS12_parse(p12, const_cast(m_keypass.c_str()), &pkey, NULL, NULL); - PKCS12_free(p12); - if (pkey) { - ret=SSL_CTX_use_PrivateKey(ctx, pkey); - EVP_PKEY_free(pkey); - } - } - } - if (in) - BIO_free(in); - } - } - - if (ret!=1) { - log_openssl(); - throw XMLSecurityException("Unable to attach private key to SSL context."); - } - - // Attach certs. - for (vector::const_iterator i=m_certs.begin(); i!=m_certs.end(); i++) { - if (i==m_certs.begin()) { - if (SSL_CTX_use_certificate(ctx, *i) != 1) { - log_openssl(); - throw XMLSecurityException("Unable to attach client certificate to SSL context."); - } - } - else { - // When we add certs, they don't get ref counted, so we need to duplicate them. - X509* dup = X509_dup(*i); - if (SSL_CTX_add_extra_chain_cert(ctx, dup) != 1) { - X509_free(dup); - log_openssl(); - throw XMLSecurityException("Unable to attach CA certificate to SSL context."); - } - } - } -} - -// Used to determine the encoding format of credentials files -// dynamically. Supports: PEM, DER, PKCS12. -FilesystemCredentialResolver::format_t FilesystemCredentialResolver::getEncodingFormat(BIO* in) const -{ - PKCS12* p12 = NULL; - format_t format; - - const int READSIZE = 1; - char buf[READSIZE]; - char b1; - int mark; - - try { - if ( (mark = BIO_tell(in)) < 0 ) - throw XMLSecurityException("getEncodingFormat: BIO_tell() can't get the file position"); - if ( BIO_read(in, buf, READSIZE) <= 0 ) - throw XMLSecurityException("getEncodingFormat: BIO_read() can't read from the stream"); - if ( BIO_seek(in, mark) < 0 ) - throw XMLSecurityException("getEncodingFormat: BIO_seek() can't reset the file position"); - } - catch (...) { - log_openssl(); - throw; - } - - b1 = buf[0]; - - // This is a slight variation of the Java code by Chad La Joie. - // - // Check the first byte of the file. If it's some kind of - // DER-encoded structure (including PKCS12), it will begin with ASCII 048. - // Otherwise, assume it's PEM. - if (b1 != 48) { - format = PEM; - } else { - // Here we know it's DER-encoded, now try to parse it as a PKCS12 - // ASN.1 structure. If it fails, must be another kind of DER-encoded - // key/cert structure. A little inefficient...but it works. - if ( (p12=d2i_PKCS12_bio(in,NULL)) == NULL ) { - format = DER; - } else { - format = _PKCS12; - } - if (p12) - PKCS12_free(p12); - if ( BIO_seek(in, mark) < 0 ) { - log_openssl(); - throw XMLSecurityException("getEncodingFormat: BIO_seek() can't reset the file position"); - } - } - - return format; -} - -// Convert key/cert format_t types to a human-meaningful string for debug output -string FilesystemCredentialResolver::formatToString(format_t format) const -{ - switch(format) { - case PEM: - return "PEM"; - case DER: - return "DER"; - case _PKCS12: - return "PKCS12"; - default: - return "UNKNOWN"; - } -} - -// Convert key/cert raw XML format attribute (XMLCh[]) to format_t type -FilesystemCredentialResolver::format_t FilesystemCredentialResolver::xmlFormatToFormat(const XMLCh* format_xml) const -{ - static const XMLCh cPEM[] = UNICODE_LITERAL_3(P,E,M); - static const XMLCh cDER[] = UNICODE_LITERAL_3(D,E,R); - static const XMLCh cPKCS12[] = { chLatin_P, chLatin_K, chLatin_C, chLatin_S, chDigit_1, chDigit_2, chNull }; - format_t format; - - if (!XMLString::compareString(format_xml,cPEM)) - format=PEM; - else if (!XMLString::compareString(format_xml,cDER)) - format=DER; - else if (!XMLString::compareString(format_xml,cPKCS12)) - format=_PKCS12; - else - format=UNKNOWN; - - return format; -} +/* + * Copyright 2001-2005 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. + */ + +/** + * FilesystemCredentialResolver.cpp + * + * Supplies credentials from local files + */ + +#include "internal.h" +#include "signature/KeyResolver.h" +#include "signature/OpenSSLCredentialResolver.h" +#include "util/NDC.h" +#include "util/XMLHelper.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace xmlsignature; +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +// OpenSSL password callback... +static int passwd_callback(char* buf, int len, int verify, void* passwd) +{ + if(!verify) + { + if(passwd && len > strlen(reinterpret_cast(passwd))) + { + strcpy(buf,reinterpret_cast(passwd)); + return strlen(buf); + } + } + return 0; +} + +namespace xmlsignature { + class FilesystemCredentialResolver : public OpenSSLCredentialResolver, public KeyResolver + { + public: + FilesystemCredentialResolver(const DOMElement* e); + virtual ~FilesystemCredentialResolver(); + + Lockable* lock() { return this; } + void unlock() {} + + XSECCryptoKey* loadKey(); + + XSECCryptoKey* getKey() const { return m_key ? m_key->clone() : NULL; } + const vector& getCertificates() const { return m_xseccerts; } + void attach(SSL_CTX* ctx) const; + + XSECCryptoKey* resolveKey(const KeyInfo* keyInfo) const { return m_key ? m_key->clone() : NULL; } + XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo) const { return m_key ? m_key->clone() : NULL; } + vector::size_type resolveCertificates(const KeyInfo* keyInfo, ResolvedCertificates& certs) const { + accessCertificates(certs).assign(m_xseccerts.begin(), m_xseccerts.end()); + accessOwned(certs) = false; + return accessCertificates(certs).size(); + } + vector::size_type resolveCertificates(DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs) const { + accessCertificates(certs).assign(m_xseccerts.begin(), m_xseccerts.end()); + accessOwned(certs) = false; + return accessCertificates(certs).size(); + } + + private: + enum format_t { PEM=SSL_FILETYPE_PEM, DER=SSL_FILETYPE_ASN1, _PKCS12, UNKNOWN }; + + format_t getEncodingFormat(BIO* in) const; + string formatToString(format_t format) const; + format_t xmlFormatToFormat(const XMLCh* format_xml) const; + + format_t m_keyformat; + string m_keypath,m_keypass; + vector m_certs; + vector m_xseccerts; + XSECCryptoKey* m_key; + }; + + CredentialResolver* XMLTOOL_DLLLOCAL FilesystemCredentialResolverFactory(const DOMElement* const & e) + { + return new FilesystemCredentialResolver(e); + } + + KeyResolver* XMLTOOL_DLLLOCAL FilesystemKeyResolverFactory(const DOMElement* const & e) + { + return new FilesystemCredentialResolver(e); + } +}; + +static const XMLCh CAPath[] = UNICODE_LITERAL_6(C,A,P,a,t,h); +static const XMLCh Certificate[] = UNICODE_LITERAL_11(C,e,r,t,i,f,i,c,a,t,e); +static const XMLCh format[] = UNICODE_LITERAL_6(f,o,r,m,a,t); +static const XMLCh Key[] = UNICODE_LITERAL_3(K,e,y); +static const XMLCh password[] = UNICODE_LITERAL_8(p,a,s,s,w,o,r,d); +static const XMLCh Path[] = UNICODE_LITERAL_4(P,a,t,h); + +FilesystemCredentialResolver::FilesystemCredentialResolver(const DOMElement* e) : m_key(NULL) +{ +#ifdef _DEBUG + NDC ndc("FilesystemCredentialResolver"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".CredentialResolver"); + + format_t fformat; + const XMLCh* format_xml=NULL; + BIO* in = NULL; + + // Move to Key + const DOMElement* root=e; + e=XMLHelper::getFirstChildElement(root,Key); + if (e) { + + // Get raw format attrib value, but defer processing til later since may need to + // determine format dynamically, and we need the Path for that. + format_xml=e->getAttributeNS(NULL,format); + + const XMLCh* password_xml=e->getAttributeNS(NULL,password); + if (password_xml) { + auto_ptr_char kp(password_xml); + m_keypass=kp.get(); + } + + e=XMLHelper::getFirstChildElement(e,Path); + if (e && e->hasChildNodes()) { + const XMLCh* s=e->getFirstChild()->getNodeValue(); + auto_ptr_char kpath(s); +#ifdef WIN32 + struct _stat stat_buf; + if (_stat(kpath.get(), &stat_buf) != 0) +#else + struct stat stat_buf; + if (stat(kpath.get(), &stat_buf) != 0) +#endif + { + log.error("key file (%s) can't be opened", kpath.get()); + throw XMLSecurityException("FilesystemCredentialResolver can't access key file ($1)",params(1,kpath.get())); + } + m_keypath=kpath.get(); + } + else { + log.error("Path element missing inside Key element"); + throw XMLSecurityException("FilesystemCredentialResolver can't access key file, no Path element specified."); + } + + // Determine the key encoding format dynamically, if not explicitly specified + if (format_xml && *format_xml) { + fformat = xmlFormatToFormat(format_xml); + if (fformat != UNKNOWN) { + m_keyformat = fformat; + } + else { + auto_ptr_char unknown(format_xml); + log.error("configuration specifies unknown key encoding format (%s)", unknown.get()); + throw XMLSecurityException("FilesystemCredentialResolver configuration contains unknown key encoding format ($1)",params(1,unknown.get())); + } + } + else { + in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,m_keypath.c_str())>0) { + m_keyformat = getEncodingFormat(in); + log.debug("key encoding format for (%s) dynamically resolved as (%s)", m_keypath.c_str(), formatToString(m_keyformat).c_str()); + } + else { + log.error("key file (%s) can't be read to determine encoding format", m_keypath.c_str()); + throw XMLSecurityException("FilesystemCredentialResolver can't read key file ($1) to determine encoding format",params(1,m_keypath.c_str())); + } + if (in) + BIO_free(in); + in = NULL; + } + + // Load the key. + m_key = loadKey(); + } + + // Check for Certificate + e=XMLHelper::getFirstChildElement(root,Certificate); + if (!e) + return; + auto_ptr_char certpass(e->getAttributeNS(NULL,password)); + + DOMElement* ep=XMLHelper::getFirstChildElement(e,Path); + if (!ep || !ep->hasChildNodes()) { + log.error("Path element missing inside Certificate element or is empty"); + throw XMLSecurityException("FilesystemCredentialResolver can't access certificate file, missing or empty Path element."); + } + + auto_ptr_char certpath(ep->getFirstChild()->getNodeValue()); + format_xml=e->getAttributeNS(NULL,format); + if (format_xml && *format_xml) { + fformat = xmlFormatToFormat(format_xml); + if (fformat == UNKNOWN) { + auto_ptr_char unknown(format_xml); + log.error("configuration specifies unknown certificate encoding format (%s)", unknown.get()); + throw XMLSecurityException("FilesystemCredentialResolver configuration contains unknown certificate encoding format ($1)",params(1,unknown.get())); + } + } + + try { + X509* x=NULL; + PKCS12* p12=NULL; + in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,certpath.get())>0) { + if (!format_xml || !*format_xml) { + // Determine the cert encoding format dynamically, if not explicitly specified + fformat = getEncodingFormat(in); + log.debug("certificate encoding format for (%s) dynamically resolved as (%s)", certpath.get(), formatToString(fformat).c_str()); + } + + switch(fformat) { + case PEM: + while (x=PEM_read_bio_X509(in,NULL,passwd_callback,const_cast(certpass.get()))) + m_certs.push_back(x); + break; + + case DER: + x=d2i_X509_bio(in,NULL); + if (x) + m_certs.push_back(x); + else { + log_openssl(); + BIO_free(in); + throw XMLSecurityException("FilesystemCredentialResolver unable to load DER certificate from file ($1)",params(1,certpath.get())); + } + break; + + case _PKCS12: + p12=d2i_PKCS12_bio(in,NULL); + if (p12) { + PKCS12_parse(p12, certpass.get(), NULL, &x, NULL); + PKCS12_free(p12); + } + if (x) { + m_certs.push_back(x); + x=NULL; + } else { + log_openssl(); + BIO_free(in); + throw XMLSecurityException("FilesystemCredentialResolver unable to load PKCS12 certificate from file ($1)",params(1,certpath.get())); + } + break; + } // end switch + + } else { + log_openssl(); + if (in) { + BIO_free(in); + in=NULL; + } + throw XMLSecurityException("FilesystemCredentialResolver unable to load certificate(s) from file ($1)",params(1,certpath.get())); + } + if (in) { + BIO_free(in); + in=NULL; + } + + if (m_certs.empty()) { + throw XMLSecurityException("FilesystemCredentialResolver unable to load any certificate(s)"); + } + + // Load any extra CA files. + DOMElement* extra=XMLHelper::getFirstChildElement(e,CAPath); + while (extra) { + if (!extra->hasChildNodes()) { + log.warn("skipping empty CAPath element"); + extra = XMLHelper::getNextSiblingElement(extra,CAPath); + continue; + } + auto_ptr_char capath(extra->getFirstChild()->getNodeValue()); + x=NULL; + p12=NULL; + in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,capath.get())>0) { + if (!format_xml || !*format_xml) { + // Determine the cert encoding format dynamically, if not explicitly specified + fformat = getEncodingFormat(in); + log.debug("CA certificate encoding format for (%s) dynamically resolved as (%s)", certpath.get(), formatToString(fformat).c_str()); + } + + switch (fformat) { + case PEM: + while (x=PEM_read_bio_X509(in,NULL,passwd_callback,const_cast(certpass.get()))) + m_certs.push_back(x); + break; + + case DER: + x=d2i_X509_bio(in,NULL); + if (x) + m_certs.push_back(x); + else { + log_openssl(); + BIO_free(in); + throw XMLSecurityException("FilesystemCredentialResolver unable to load DER CA certificate from file ($1)",params(1,capath.get())); + } + break; + + case _PKCS12: + p12 = d2i_PKCS12_bio(in, NULL); + if (p12) { + PKCS12_parse(p12, certpass.get(), NULL, &x, NULL); + PKCS12_free(p12); + } + if (x) { + m_certs.push_back(x); + x=NULL; + } + else { + log_openssl(); + BIO_free(in); + throw XMLSecurityException("FilesystemCredentialResolver unable to load PKCS12 CA certificate from file ($1)",params(1,capath.get())); + } + break; + } //end switch + + BIO_free(in); + } + else { + if (in) + BIO_free(in); + log_openssl(); + log.error("CA file (%s) can't be opened", capath.get()); + throw XMLSecurityException("FilesystemCredentialResolver can't open CA file ($1)",params(1,capath.get())); + } + + extra = XMLHelper::getNextSiblingElement(extra,CAPath); + } + } + catch (XMLToolingException&) { + for (vector::iterator j=m_certs.begin(); j!=m_certs.end(); j++) + X509_free(*j); + throw; + } + + // Reflect certs over to XSEC form. + for (vector::iterator j=m_certs.begin(); j!=m_certs.end(); j++) + m_xseccerts.push_back(new OpenSSLCryptoX509(*j)); +} + +XSECCryptoKey* FilesystemCredentialResolver::loadKey() +{ +#ifdef _DEBUG + NDC ndc("loadKey"); +#endif + + // Get a EVP_PKEY. + EVP_PKEY* pkey=NULL; + BIO* in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,m_keypath.c_str())>0) { + switch (m_keyformat) { + case PEM: + pkey=PEM_read_bio_PrivateKey(in, NULL, passwd_callback, const_cast(m_keypass.c_str())); + break; + + case DER: + pkey=d2i_PrivateKey_bio(in, NULL); + break; + + default: { + PKCS12* p12 = d2i_PKCS12_bio(in, NULL); + if (p12) { + PKCS12_parse(p12, const_cast(m_keypass.c_str()), &pkey, NULL, NULL); + PKCS12_free(p12); + } + } + } + } + if (in) + BIO_free(in); + + // Now map it to an XSEC wrapper. + if (pkey) { + XSECCryptoKey* ret=NULL; + switch (pkey->type) { + case EVP_PKEY_RSA: + ret=new OpenSSLCryptoKeyRSA(pkey); + break; + + case EVP_PKEY_DSA: + ret=new OpenSSLCryptoKeyDSA(pkey); + break; + + default: + Category::getInstance(XMLTOOLING_LOGCAT".CredentialResolver").error("unsupported private key type"); + } + EVP_PKEY_free(pkey); + if (ret) + return ret; + } + + log_openssl(); + throw XMLSecurityException("FilesystemCredentialResolver unable to load private key from file."); +} + +FilesystemCredentialResolver::~FilesystemCredentialResolver() +{ + delete m_key; + for_each(m_certs.begin(),m_certs.end(),X509_free); + for_each(m_xseccerts.begin(),m_xseccerts.end(),xmltooling::cleanup()); +} + +void FilesystemCredentialResolver::attach(SSL_CTX* ctx) const +{ +#ifdef _DEBUG + NDC ndc("attach"); +#endif + + // Attach key. + SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); + SSL_CTX_set_default_passwd_cb_userdata(ctx, const_cast(m_keypass.c_str())); + + int ret=0; + switch (m_keyformat) { + case PEM: + ret=SSL_CTX_use_PrivateKey_file(ctx, m_keypath.c_str(), m_keyformat); + break; + + case DER: + ret=SSL_CTX_use_RSAPrivateKey_file(ctx, m_keypath.c_str(), m_keyformat); + break; + + default: { + BIO* in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,m_keypath.c_str())>0) { + EVP_PKEY* pkey=NULL; + PKCS12* p12 = d2i_PKCS12_bio(in, NULL); + if (p12) { + PKCS12_parse(p12, const_cast(m_keypass.c_str()), &pkey, NULL, NULL); + PKCS12_free(p12); + if (pkey) { + ret=SSL_CTX_use_PrivateKey(ctx, pkey); + EVP_PKEY_free(pkey); + } + } + } + if (in) + BIO_free(in); + } + } + + if (ret!=1) { + log_openssl(); + throw XMLSecurityException("Unable to attach private key to SSL context."); + } + + // Attach certs. + for (vector::const_iterator i=m_certs.begin(); i!=m_certs.end(); i++) { + if (i==m_certs.begin()) { + if (SSL_CTX_use_certificate(ctx, *i) != 1) { + log_openssl(); + throw XMLSecurityException("Unable to attach client certificate to SSL context."); + } + } + else { + // When we add certs, they don't get ref counted, so we need to duplicate them. + X509* dup = X509_dup(*i); + if (SSL_CTX_add_extra_chain_cert(ctx, dup) != 1) { + X509_free(dup); + log_openssl(); + throw XMLSecurityException("Unable to attach CA certificate to SSL context."); + } + } + } +} + +// Used to determine the encoding format of credentials files +// dynamically. Supports: PEM, DER, PKCS12. +FilesystemCredentialResolver::format_t FilesystemCredentialResolver::getEncodingFormat(BIO* in) const +{ + PKCS12* p12 = NULL; + format_t format; + + const int READSIZE = 1; + char buf[READSIZE]; + char b1; + int mark; + + try { + if ( (mark = BIO_tell(in)) < 0 ) + throw XMLSecurityException("getEncodingFormat: BIO_tell() can't get the file position"); + if ( BIO_read(in, buf, READSIZE) <= 0 ) + throw XMLSecurityException("getEncodingFormat: BIO_read() can't read from the stream"); + if ( BIO_seek(in, mark) < 0 ) + throw XMLSecurityException("getEncodingFormat: BIO_seek() can't reset the file position"); + } + catch (...) { + log_openssl(); + throw; + } + + b1 = buf[0]; + + // This is a slight variation of the Java code by Chad La Joie. + // + // Check the first byte of the file. If it's some kind of + // DER-encoded structure (including PKCS12), it will begin with ASCII 048. + // Otherwise, assume it's PEM. + if (b1 != 48) { + format = PEM; + } else { + // Here we know it's DER-encoded, now try to parse it as a PKCS12 + // ASN.1 structure. If it fails, must be another kind of DER-encoded + // key/cert structure. A little inefficient...but it works. + if ( (p12=d2i_PKCS12_bio(in,NULL)) == NULL ) { + format = DER; + } else { + format = _PKCS12; + } + if (p12) + PKCS12_free(p12); + if ( BIO_seek(in, mark) < 0 ) { + log_openssl(); + throw XMLSecurityException("getEncodingFormat: BIO_seek() can't reset the file position"); + } + } + + return format; +} + +// Convert key/cert format_t types to a human-meaningful string for debug output +string FilesystemCredentialResolver::formatToString(format_t format) const +{ + switch(format) { + case PEM: + return "PEM"; + case DER: + return "DER"; + case _PKCS12: + return "PKCS12"; + default: + return "UNKNOWN"; + } +} + +// Convert key/cert raw XML format attribute (XMLCh[]) to format_t type +FilesystemCredentialResolver::format_t FilesystemCredentialResolver::xmlFormatToFormat(const XMLCh* format_xml) const +{ + static const XMLCh cPEM[] = UNICODE_LITERAL_3(P,E,M); + static const XMLCh cDER[] = UNICODE_LITERAL_3(D,E,R); + static const XMLCh cPKCS12[] = { chLatin_P, chLatin_K, chLatin_C, chLatin_S, chDigit_1, chDigit_2, chNull }; + format_t format; + + if (!XMLString::compareString(format_xml,cPEM)) + format=PEM; + else if (!XMLString::compareString(format_xml,cDER)) + format=DER; + else if (!XMLString::compareString(format_xml,cPKCS12)) + format=_PKCS12; + else + format=UNKNOWN; + + return format; +} diff --git a/xmltooling/signature/impl/InlineKeyResolver.cpp b/xmltooling/signature/impl/InlineKeyResolver.cpp index 9ad79df..9f06f64 100644 --- a/xmltooling/signature/impl/InlineKeyResolver.cpp +++ b/xmltooling/signature/impl/InlineKeyResolver.cpp @@ -1,463 +1,463 @@ -/* - * Copyright 2001-2005 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. - */ - -/** - * InlineKeyResolver.cpp - * - * Resolves key information directly from recognized KeyInfo structures. - */ - -#include "internal.h" -#include "signature/CachingKeyResolver.h" -#include "signature/KeyInfo.h" -#include "util/NDC.h" -#include "util/Threads.h" -#include "util/XMLConstants.h" -#include "validation/ValidatorSuite.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace xmlsignature; -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -namespace xmlsignature { - class XMLTOOL_DLLLOCAL InlineKeyResolver : public CachingKeyResolver - { - public: - InlineKeyResolver(const DOMElement* e); - virtual ~InlineKeyResolver(); - - XSECCryptoKey* resolveKey(const KeyInfo* keyInfo) const; - XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo) const; - vector::size_type resolveCertificates(const KeyInfo* keyInfo, ResolvedCertificates& certs) const; - vector::size_type resolveCertificates(DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs) const; - XSECCryptoX509CRL* resolveCRL(const KeyInfo* keyInfo) const; - XSECCryptoX509CRL* resolveCRL(DSIGKeyInfoList* keyInfo) const; - - void clearCache() { - if (m_lock) - m_lock->wrlock(); - m_cache.clear(); - if (m_lock) - m_lock->unlock(); - } - - private: - struct XMLTOOL_DLLLOCAL CacheEntry { - CacheEntry() : m_key(NULL), m_crl(NULL) {} - ~CacheEntry() { - delete m_key; - for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup()); - delete m_crl; - } - XSECCryptoKey* m_key; - vector m_certs; - XSECCryptoX509CRL* m_crl; - }; - - void _resolve(const KeyInfo* keyInfo, CacheEntry& entry) const; - XSECCryptoKey* _resolveKey(const KeyInfo* keyInfo) const; - vector::size_type _resolveCertificates(const KeyInfo* keyInfo, vector& certs) const; - XSECCryptoX509CRL* _resolveCRL(const KeyInfo* keyInfo) const; - - RWLock* m_lock; - mutable map m_cache; - }; - - KeyResolver* XMLTOOL_DLLLOCAL InlineKeyResolverFactory(const DOMElement* const & e) - { - return new InlineKeyResolver(e); - } -}; - -static const XMLCh cache[] = UNICODE_LITERAL_5(c,a,c,h,e); - -InlineKeyResolver::InlineKeyResolver(const DOMElement* e) : m_lock(NULL) -{ - const XMLCh* flag = e ? e->getAttributeNS(NULL,cache) : NULL; - if (flag && XMLString::equals(flag,XMLConstants::XML_TRUE) || XMLString::equals(flag,XMLConstants::XML_ONE)) - m_lock=RWLock::create(); -} - -InlineKeyResolver::~InlineKeyResolver() -{ - clearCache(); - delete m_lock; -} - -void InlineKeyResolver::_resolve(const KeyInfo* keyInfo, CacheEntry& entry) const -{ - if (_resolveCertificates(keyInfo, entry.m_certs)>0) - entry.m_key = entry.m_certs.front()->clonePublicKey(); - else - entry.m_key = _resolveKey(keyInfo); - entry.m_crl = _resolveCRL(keyInfo); -} - -XSECCryptoKey* InlineKeyResolver::_resolveKey(const KeyInfo* keyInfo) const -{ -#ifdef _DEBUG - NDC ndc("_resolveKey"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver"); - - if (!keyInfo) - return NULL; - - // Check for ds:X509Data - const vector& x509Datas=keyInfo->getX509Datas(); - for (vector::const_iterator j=x509Datas.begin(); j!=x509Datas.end(); ++j) { - try { - const vector x509Certs=const_cast(*j)->getX509Certificates(); - if (!x509Certs.empty()) { - auto_ptr_char x(x509Certs.front()->getValue()); - if (!x.get()) { - log.warn("skipping empty ds:X509Certificate"); - } - else { - log.debug("resolving ds:X509Certificate"); - auto_ptr x509(XSECPlatformUtils::g_cryptoProvider->X509()); - x509->loadX509Base64Bin(x.get(), strlen(x.get())); - return x509->clonePublicKey(); - } - } - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - log.error("caught XML-Security exception loading certificate: %s", temp.get()); - } - catch(XSECCryptoException& e) { - log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); - } - } - - // Check for ds:KeyValue - const vector& keyValues = keyInfo->getKeyValues(); - for (vector::const_iterator i=keyValues.begin(); i!=keyValues.end(); ++i) { - try { - SchemaValidators.validate(*i); // see if it's a "valid" key - RSAKeyValue* rsakv = (*i)->getRSAKeyValue(); - if (rsakv) { - log.debug("resolving ds:RSAKeyValue"); - auto_ptr_char mod(rsakv->getModulus()->getValue()); - auto_ptr_char exp(rsakv->getExponent()->getValue()); - auto_ptr rsa(XSECPlatformUtils::g_cryptoProvider->keyRSA()); - rsa->loadPublicModulusBase64BigNums(mod.get(), strlen(mod.get())); - rsa->loadPublicExponentBase64BigNums(exp.get(), strlen(exp.get())); - return rsa.release(); - } - DSAKeyValue* dsakv = (*i)->getDSAKeyValue(); - if (dsakv) { - log.debug("resolving ds:DSAKeyValue"); - auto_ptr dsa(XSECPlatformUtils::g_cryptoProvider->keyDSA()); - auto_ptr_char y(dsakv->getY()->getValue()); - dsa->loadYBase64BigNums(y.get(), strlen(y.get())); - if (dsakv->getP()) { - auto_ptr_char p(dsakv->getP()->getValue()); - dsa->loadPBase64BigNums(p.get(), strlen(p.get())); - } - if (dsakv->getQ()) { - auto_ptr_char q(dsakv->getQ()->getValue()); - dsa->loadQBase64BigNums(q.get(), strlen(q.get())); - } - if (dsakv->getG()) { - auto_ptr_char g(dsakv->getG()->getValue()); - dsa->loadGBase64BigNums(g.get(), strlen(g.get())); - } - return dsa.release(); - } - } - catch (ValidationException& ex) { - log.warn("skipping invalid ds:KeyValue (%s)", ex.what()); - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - log.error("caught XML-Security exception loading key: %s", temp.get()); - } - catch(XSECCryptoException& e) { - log.error("caught XML-Security exception loading key: %s", e.getMsg()); - } - } - - log.warn("unable to resolve key"); - return NULL; -} - -vector::size_type InlineKeyResolver::_resolveCertificates( - const KeyInfo* keyInfo, vector& certs - ) const -{ -#ifdef _DEBUG - NDC ndc("_resolveCertificates"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver"); - - if (!keyInfo) - return 0; - - // Check for ds:X509Data - const vector& x509Datas=keyInfo->getX509Datas(); - for (vector::const_iterator j=x509Datas.begin(); certs.empty() && j!=x509Datas.end(); ++j) { - const vector x509Certs=const_cast(*j)->getX509Certificates(); - for (vector::const_iterator k=x509Certs.begin(); k!=x509Certs.end(); ++k) { - try { - auto_ptr_char x((*k)->getValue()); - if (!x.get()) { - log.warn("skipping empty ds:X509Certificate"); - } - else { - log.debug("resolving ds:X509Certificate"); - auto_ptr x509(XSECPlatformUtils::g_cryptoProvider->X509()); - x509->loadX509Base64Bin(x.get(), strlen(x.get())); - certs.push_back(x509.release()); - } - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - log.error("caught XML-Security exception loading certificate: %s", temp.get()); - } - catch(XSECCryptoException& e) { - log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); - } - } - } - if (log.isDebugEnabled()) { - log.debug("resolved %d certificate%s", certs.size(), certs.size()==1 ? "" : "s"); - } - return certs.size(); -} - -XSECCryptoX509CRL* InlineKeyResolver::_resolveCRL(const KeyInfo* keyInfo) const -{ -#ifdef _DEBUG - NDC ndc("_resolveCRL"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver"); - - if (!keyInfo) - return NULL; - - // Check for ds:X509Data - const vector& x509Datas=keyInfo->getX509Datas(); - for (vector::const_iterator j=x509Datas.begin(); j!=x509Datas.end(); ++j) { - const vector x509CRLs=const_cast(*j)->getX509CRLs(); - for (vector::const_iterator k=x509CRLs.begin(); k!=x509CRLs.end(); ++k) { - try { - auto_ptr_char x((*k)->getValue()); - if (!x.get()) { - log.warn("skipping empty ds:X509CRL"); - } - else { - log.debug("resolving ds:X509CRL"); - auto_ptr crl(XMLToolingConfig::getConfig().X509CRL()); - crl->loadX509CRLBase64Bin(x.get(), strlen(x.get())); - return crl.release(); - } - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - log.error("caught XML-Security exception loading certificate: %s", temp.get()); - } - catch(XSECCryptoException& e) { - log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); - } - } - } - return NULL; -} - -XSECCryptoKey* InlineKeyResolver::resolveKey(const KeyInfo* keyInfo) const -{ - // Caching? - if (m_lock) { - // Get read lock. - m_lock->rdlock(); - map::iterator i=m_cache.find(keyInfo); - if (i != m_cache.end()) { - // Found in cache, so just return the results. - SharedLock locker(m_lock,false); - return i->second.m_key ? i->second.m_key->clone() : NULL; - } - else { - // Elevate lock. - m_lock->unlock(); - m_lock->wrlock(); - SharedLock locker(m_lock,false); - // Recheck cache. - i=m_cache.find(keyInfo); - if (i == m_cache.end()) { - i = m_cache.insert(make_pair(keyInfo,CacheEntry())).first; - _resolve(i->first, i->second); - } - return i->second.m_key ? i->second.m_key->clone() : NULL; - } - } - return _resolveKey(keyInfo); -} - -XSECCryptoX509CRL* InlineKeyResolver::resolveCRL(const KeyInfo* keyInfo) const -{ - // Caching? - if (m_lock) { - // Get read lock. - m_lock->rdlock(); - map::iterator i=m_cache.find(keyInfo); - if (i != m_cache.end()) { - // Found in cache, so just return the results. - SharedLock locker(m_lock,false); - return i->second.m_crl ? i->second.m_crl->clone() : NULL; - } - else { - // Elevate lock. - m_lock->unlock(); - m_lock->wrlock(); - SharedLock locker(m_lock,false); - // Recheck cache. - i=m_cache.find(keyInfo); - if (i == m_cache.end()) { - i = m_cache.insert(make_pair(keyInfo,CacheEntry())).first; - _resolve(i->first, i->second); - } - return i->second.m_crl ? i->second.m_crl->clone() : NULL; - } - } - return _resolveCRL(keyInfo); -} - -vector::size_type InlineKeyResolver::resolveCertificates( - const KeyInfo* keyInfo, ResolvedCertificates& certs - ) const -{ - // Caching? - if (m_lock) { - // Get read lock. - m_lock->rdlock(); - map::iterator i=m_cache.find(keyInfo); - if (i != m_cache.end()) { - // Found in cache, so just return the results. - SharedLock locker(m_lock,false); - accessCertificates(certs).assign(i->second.m_certs.begin(), i->second.m_certs.end()); - accessOwned(certs) = false; - return accessCertificates(certs).size(); - } - else { - // Elevate lock. - m_lock->unlock(); - m_lock->wrlock(); - SharedLock locker(m_lock,false); - // Recheck cache. - i=m_cache.find(keyInfo); - if (i == m_cache.end()) { - i = m_cache.insert(make_pair(keyInfo,CacheEntry())).first; - _resolve(i->first, i->second); - } - accessCertificates(certs).assign(i->second.m_certs.begin(), i->second.m_certs.end()); - accessOwned(certs) = false; - return accessCertificates(certs).size(); - } - } - accessOwned(certs) = true; - return _resolveCertificates(keyInfo, accessCertificates(certs)); -} - -XSECCryptoKey* InlineKeyResolver::resolveKey(DSIGKeyInfoList* keyInfo) const -{ -#ifdef _DEBUG - NDC ndc("resolveKey"); -#endif - - if (!keyInfo) - return NULL; - - // Default resolver handles RSA/DSAKeyValue and X509Certificate elements. - try { - XSECKeyInfoResolverDefault def; - return def.resolveKey(keyInfo); - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading certificate: %s", temp.get()); - } - catch(XSECCryptoException& e) { - Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading certificate: %s", e.getMsg()); - } - return NULL; -} - -vector::size_type InlineKeyResolver::resolveCertificates( - DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs - ) const -{ - accessCertificates(certs).clear(); - accessOwned(certs) = false; - - if (!keyInfo) - return 0; - - DSIGKeyInfoList::size_type sz = keyInfo->getSize(); - for (DSIGKeyInfoList::size_type i=0; accessCertificates(certs).empty() && iitem(i)->getKeyInfoType()==DSIGKeyInfo::KEYINFO_X509) { - DSIGKeyInfoX509* x509 = static_cast(keyInfo->item(i)); - int count = x509->getCertificateListSize(); - for (int j=0; jgetCertificateCryptoItem(j)); - } - } - } - return accessCertificates(certs).size(); -} - -XSECCryptoX509CRL* InlineKeyResolver::resolveCRL(DSIGKeyInfoList* keyInfo) const -{ -#ifdef _DEBUG - NDC ndc("resolveCRL"); -#endif - - if (!keyInfo) - return NULL; - - DSIGKeyInfoList::size_type sz = keyInfo->getSize(); - for (DSIGKeyInfoList::size_type i=0; iitem(i)->getKeyInfoType()==DSIGKeyInfo::KEYINFO_X509) { - auto_ptr_char buf(static_cast(keyInfo->item(i))->getX509CRL()); - if (buf.get()) { - try { - auto_ptr crlobj(XMLToolingConfig::getConfig().X509CRL()); - crlobj->loadX509CRLBase64Bin(buf.get(), strlen(buf.get())); - return crlobj.release(); - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading CRL: %s", temp.get()); - } - catch(XSECCryptoException& e) { - Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading CRL: %s", e.getMsg()); - } - } - } - } - return NULL; -} +/* + * Copyright 2001-2005 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. + */ + +/** + * InlineKeyResolver.cpp + * + * Resolves key information directly from recognized KeyInfo structures. + */ + +#include "internal.h" +#include "signature/CachingKeyResolver.h" +#include "signature/KeyInfo.h" +#include "util/NDC.h" +#include "util/Threads.h" +#include "util/XMLConstants.h" +#include "validation/ValidatorSuite.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace xmlsignature; +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +namespace xmlsignature { + class XMLTOOL_DLLLOCAL InlineKeyResolver : public CachingKeyResolver + { + public: + InlineKeyResolver(const DOMElement* e); + virtual ~InlineKeyResolver(); + + XSECCryptoKey* resolveKey(const KeyInfo* keyInfo) const; + XSECCryptoKey* resolveKey(DSIGKeyInfoList* keyInfo) const; + vector::size_type resolveCertificates(const KeyInfo* keyInfo, ResolvedCertificates& certs) const; + vector::size_type resolveCertificates(DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs) const; + XSECCryptoX509CRL* resolveCRL(const KeyInfo* keyInfo) const; + XSECCryptoX509CRL* resolveCRL(DSIGKeyInfoList* keyInfo) const; + + void clearCache() { + if (m_lock) + m_lock->wrlock(); + m_cache.clear(); + if (m_lock) + m_lock->unlock(); + } + + private: + struct XMLTOOL_DLLLOCAL CacheEntry { + CacheEntry() : m_key(NULL), m_crl(NULL) {} + ~CacheEntry() { + delete m_key; + for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup()); + delete m_crl; + } + XSECCryptoKey* m_key; + vector m_certs; + XSECCryptoX509CRL* m_crl; + }; + + void _resolve(const KeyInfo* keyInfo, CacheEntry& entry) const; + XSECCryptoKey* _resolveKey(const KeyInfo* keyInfo) const; + vector::size_type _resolveCertificates(const KeyInfo* keyInfo, vector& certs) const; + XSECCryptoX509CRL* _resolveCRL(const KeyInfo* keyInfo) const; + + RWLock* m_lock; + mutable map m_cache; + }; + + KeyResolver* XMLTOOL_DLLLOCAL InlineKeyResolverFactory(const DOMElement* const & e) + { + return new InlineKeyResolver(e); + } +}; + +static const XMLCh cache[] = UNICODE_LITERAL_5(c,a,c,h,e); + +InlineKeyResolver::InlineKeyResolver(const DOMElement* e) : m_lock(NULL) +{ + const XMLCh* flag = e ? e->getAttributeNS(NULL,cache) : NULL; + if (flag && XMLString::equals(flag,XMLConstants::XML_TRUE) || XMLString::equals(flag,XMLConstants::XML_ONE)) + m_lock=RWLock::create(); +} + +InlineKeyResolver::~InlineKeyResolver() +{ + clearCache(); + delete m_lock; +} + +void InlineKeyResolver::_resolve(const KeyInfo* keyInfo, CacheEntry& entry) const +{ + if (_resolveCertificates(keyInfo, entry.m_certs)>0) + entry.m_key = entry.m_certs.front()->clonePublicKey(); + else + entry.m_key = _resolveKey(keyInfo); + entry.m_crl = _resolveCRL(keyInfo); +} + +XSECCryptoKey* InlineKeyResolver::_resolveKey(const KeyInfo* keyInfo) const +{ +#ifdef _DEBUG + NDC ndc("_resolveKey"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver"); + + if (!keyInfo) + return NULL; + + // Check for ds:X509Data + const vector& x509Datas=keyInfo->getX509Datas(); + for (vector::const_iterator j=x509Datas.begin(); j!=x509Datas.end(); ++j) { + try { + const vector x509Certs=const_cast(*j)->getX509Certificates(); + if (!x509Certs.empty()) { + auto_ptr_char x(x509Certs.front()->getValue()); + if (!x.get()) { + log.warn("skipping empty ds:X509Certificate"); + } + else { + log.debug("resolving ds:X509Certificate"); + auto_ptr x509(XSECPlatformUtils::g_cryptoProvider->X509()); + x509->loadX509Base64Bin(x.get(), strlen(x.get())); + return x509->clonePublicKey(); + } + } + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + log.error("caught XML-Security exception loading certificate: %s", temp.get()); + } + catch(XSECCryptoException& e) { + log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); + } + } + + // Check for ds:KeyValue + const vector& keyValues = keyInfo->getKeyValues(); + for (vector::const_iterator i=keyValues.begin(); i!=keyValues.end(); ++i) { + try { + SchemaValidators.validate(*i); // see if it's a "valid" key + RSAKeyValue* rsakv = (*i)->getRSAKeyValue(); + if (rsakv) { + log.debug("resolving ds:RSAKeyValue"); + auto_ptr_char mod(rsakv->getModulus()->getValue()); + auto_ptr_char exp(rsakv->getExponent()->getValue()); + auto_ptr rsa(XSECPlatformUtils::g_cryptoProvider->keyRSA()); + rsa->loadPublicModulusBase64BigNums(mod.get(), strlen(mod.get())); + rsa->loadPublicExponentBase64BigNums(exp.get(), strlen(exp.get())); + return rsa.release(); + } + DSAKeyValue* dsakv = (*i)->getDSAKeyValue(); + if (dsakv) { + log.debug("resolving ds:DSAKeyValue"); + auto_ptr dsa(XSECPlatformUtils::g_cryptoProvider->keyDSA()); + auto_ptr_char y(dsakv->getY()->getValue()); + dsa->loadYBase64BigNums(y.get(), strlen(y.get())); + if (dsakv->getP()) { + auto_ptr_char p(dsakv->getP()->getValue()); + dsa->loadPBase64BigNums(p.get(), strlen(p.get())); + } + if (dsakv->getQ()) { + auto_ptr_char q(dsakv->getQ()->getValue()); + dsa->loadQBase64BigNums(q.get(), strlen(q.get())); + } + if (dsakv->getG()) { + auto_ptr_char g(dsakv->getG()->getValue()); + dsa->loadGBase64BigNums(g.get(), strlen(g.get())); + } + return dsa.release(); + } + } + catch (ValidationException& ex) { + log.warn("skipping invalid ds:KeyValue (%s)", ex.what()); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + log.error("caught XML-Security exception loading key: %s", temp.get()); + } + catch(XSECCryptoException& e) { + log.error("caught XML-Security exception loading key: %s", e.getMsg()); + } + } + + log.warn("unable to resolve key"); + return NULL; +} + +vector::size_type InlineKeyResolver::_resolveCertificates( + const KeyInfo* keyInfo, vector& certs + ) const +{ +#ifdef _DEBUG + NDC ndc("_resolveCertificates"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver"); + + if (!keyInfo) + return 0; + + // Check for ds:X509Data + const vector& x509Datas=keyInfo->getX509Datas(); + for (vector::const_iterator j=x509Datas.begin(); certs.empty() && j!=x509Datas.end(); ++j) { + const vector x509Certs=const_cast(*j)->getX509Certificates(); + for (vector::const_iterator k=x509Certs.begin(); k!=x509Certs.end(); ++k) { + try { + auto_ptr_char x((*k)->getValue()); + if (!x.get()) { + log.warn("skipping empty ds:X509Certificate"); + } + else { + log.debug("resolving ds:X509Certificate"); + auto_ptr x509(XSECPlatformUtils::g_cryptoProvider->X509()); + x509->loadX509Base64Bin(x.get(), strlen(x.get())); + certs.push_back(x509.release()); + } + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + log.error("caught XML-Security exception loading certificate: %s", temp.get()); + } + catch(XSECCryptoException& e) { + log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); + } + } + } + if (log.isDebugEnabled()) { + log.debug("resolved %d certificate%s", certs.size(), certs.size()==1 ? "" : "s"); + } + return certs.size(); +} + +XSECCryptoX509CRL* InlineKeyResolver::_resolveCRL(const KeyInfo* keyInfo) const +{ +#ifdef _DEBUG + NDC ndc("_resolveCRL"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver"); + + if (!keyInfo) + return NULL; + + // Check for ds:X509Data + const vector& x509Datas=keyInfo->getX509Datas(); + for (vector::const_iterator j=x509Datas.begin(); j!=x509Datas.end(); ++j) { + const vector x509CRLs=const_cast(*j)->getX509CRLs(); + for (vector::const_iterator k=x509CRLs.begin(); k!=x509CRLs.end(); ++k) { + try { + auto_ptr_char x((*k)->getValue()); + if (!x.get()) { + log.warn("skipping empty ds:X509CRL"); + } + else { + log.debug("resolving ds:X509CRL"); + auto_ptr crl(XMLToolingConfig::getConfig().X509CRL()); + crl->loadX509CRLBase64Bin(x.get(), strlen(x.get())); + return crl.release(); + } + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + log.error("caught XML-Security exception loading certificate: %s", temp.get()); + } + catch(XSECCryptoException& e) { + log.error("caught XML-Security exception loading certificate: %s", e.getMsg()); + } + } + } + return NULL; +} + +XSECCryptoKey* InlineKeyResolver::resolveKey(const KeyInfo* keyInfo) const +{ + // Caching? + if (m_lock) { + // Get read lock. + m_lock->rdlock(); + map::iterator i=m_cache.find(keyInfo); + if (i != m_cache.end()) { + // Found in cache, so just return the results. + SharedLock locker(m_lock,false); + return i->second.m_key ? i->second.m_key->clone() : NULL; + } + else { + // Elevate lock. + m_lock->unlock(); + m_lock->wrlock(); + SharedLock locker(m_lock,false); + // Recheck cache. + i=m_cache.find(keyInfo); + if (i == m_cache.end()) { + i = m_cache.insert(make_pair(keyInfo,CacheEntry())).first; + _resolve(i->first, i->second); + } + return i->second.m_key ? i->second.m_key->clone() : NULL; + } + } + return _resolveKey(keyInfo); +} + +XSECCryptoX509CRL* InlineKeyResolver::resolveCRL(const KeyInfo* keyInfo) const +{ + // Caching? + if (m_lock) { + // Get read lock. + m_lock->rdlock(); + map::iterator i=m_cache.find(keyInfo); + if (i != m_cache.end()) { + // Found in cache, so just return the results. + SharedLock locker(m_lock,false); + return i->second.m_crl ? i->second.m_crl->clone() : NULL; + } + else { + // Elevate lock. + m_lock->unlock(); + m_lock->wrlock(); + SharedLock locker(m_lock,false); + // Recheck cache. + i=m_cache.find(keyInfo); + if (i == m_cache.end()) { + i = m_cache.insert(make_pair(keyInfo,CacheEntry())).first; + _resolve(i->first, i->second); + } + return i->second.m_crl ? i->second.m_crl->clone() : NULL; + } + } + return _resolveCRL(keyInfo); +} + +vector::size_type InlineKeyResolver::resolveCertificates( + const KeyInfo* keyInfo, ResolvedCertificates& certs + ) const +{ + // Caching? + if (m_lock) { + // Get read lock. + m_lock->rdlock(); + map::iterator i=m_cache.find(keyInfo); + if (i != m_cache.end()) { + // Found in cache, so just return the results. + SharedLock locker(m_lock,false); + accessCertificates(certs).assign(i->second.m_certs.begin(), i->second.m_certs.end()); + accessOwned(certs) = false; + return accessCertificates(certs).size(); + } + else { + // Elevate lock. + m_lock->unlock(); + m_lock->wrlock(); + SharedLock locker(m_lock,false); + // Recheck cache. + i=m_cache.find(keyInfo); + if (i == m_cache.end()) { + i = m_cache.insert(make_pair(keyInfo,CacheEntry())).first; + _resolve(i->first, i->second); + } + accessCertificates(certs).assign(i->second.m_certs.begin(), i->second.m_certs.end()); + accessOwned(certs) = false; + return accessCertificates(certs).size(); + } + } + accessOwned(certs) = true; + return _resolveCertificates(keyInfo, accessCertificates(certs)); +} + +XSECCryptoKey* InlineKeyResolver::resolveKey(DSIGKeyInfoList* keyInfo) const +{ +#ifdef _DEBUG + NDC ndc("resolveKey"); +#endif + + if (!keyInfo) + return NULL; + + // Default resolver handles RSA/DSAKeyValue and X509Certificate elements. + try { + XSECKeyInfoResolverDefault def; + return def.resolveKey(keyInfo); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading certificate: %s", temp.get()); + } + catch(XSECCryptoException& e) { + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading certificate: %s", e.getMsg()); + } + return NULL; +} + +vector::size_type InlineKeyResolver::resolveCertificates( + DSIGKeyInfoList* keyInfo, ResolvedCertificates& certs + ) const +{ + accessCertificates(certs).clear(); + accessOwned(certs) = false; + + if (!keyInfo) + return 0; + + DSIGKeyInfoList::size_type sz = keyInfo->getSize(); + for (DSIGKeyInfoList::size_type i=0; accessCertificates(certs).empty() && iitem(i)->getKeyInfoType()==DSIGKeyInfo::KEYINFO_X509) { + DSIGKeyInfoX509* x509 = static_cast(keyInfo->item(i)); + int count = x509->getCertificateListSize(); + for (int j=0; jgetCertificateCryptoItem(j)); + } + } + } + return accessCertificates(certs).size(); +} + +XSECCryptoX509CRL* InlineKeyResolver::resolveCRL(DSIGKeyInfoList* keyInfo) const +{ +#ifdef _DEBUG + NDC ndc("resolveCRL"); +#endif + + if (!keyInfo) + return NULL; + + DSIGKeyInfoList::size_type sz = keyInfo->getSize(); + for (DSIGKeyInfoList::size_type i=0; iitem(i)->getKeyInfoType()==DSIGKeyInfo::KEYINFO_X509) { + auto_ptr_char buf(static_cast(keyInfo->item(i))->getX509CRL()); + if (buf.get()) { + try { + auto_ptr crlobj(XMLToolingConfig::getConfig().X509CRL()); + crlobj->loadX509CRLBase64Bin(buf.get(), strlen(buf.get())); + return crlobj.release(); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading CRL: %s", temp.get()); + } + catch(XSECCryptoException& e) { + Category::getInstance(XMLTOOLING_LOGCAT".KeyResolver").error("caught XML-Security exception loading CRL: %s", e.getMsg()); + } + } + } + } + return NULL; +} diff --git a/xmltooling/signature/impl/SignatureValidator.cpp b/xmltooling/signature/impl/SignatureValidator.cpp index ac65a40..e1bb903 100644 --- a/xmltooling/signature/impl/SignatureValidator.cpp +++ b/xmltooling/signature/impl/SignatureValidator.cpp @@ -1,64 +1,64 @@ -/* - * 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. - */ - -/** - * SignatureValidator.cpp - * - * Validator for signatures based on an externally-supplied key - */ - -#include "internal.h" -#include "signature/SignatureValidator.h" - -#include -#include - -using namespace xmlsignature; -using namespace xmltooling; -using namespace std; - -void SignatureValidator::validate(const XMLObject* xmlObject) const -{ - const Signature* sigObj=dynamic_cast(xmlObject); - if (!sigObj) - throw ValidationException("Validator only applies to Signature objects."); - validate(sigObj); -} - -void SignatureValidator::validate(const Signature* sigObj) const -{ - DSIGSignature* sig=sigObj->getXMLSignature(); - if (!sig) - throw ValidationException("Signature does not exist yet."); - else if (!m_key && !m_resolver) - throw ValidationException("No KeyResolver or signing key set on Validator."); - - try { - XSECCryptoKey* key = m_key ? m_key->clone() : m_resolver->resolveKey(sig->getKeyInfoList()); - if (!key) - throw ValidationException("Unable to resolve signing key."); - sig->setSigningKey(key); - if (!sig->verify()) - throw ValidationException("Digital signature does not validate with the given key."); - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - throw ValidationException(string("Caught an XMLSecurity exception verifying signature: ") + temp.get()); - } - catch(XSECCryptoException& e) { - throw ValidationException(string("Caught an XMLSecurity exception verifying signature: ") + e.getMsg()); - } -} +/* + * 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. + */ + +/** + * SignatureValidator.cpp + * + * Validator for signatures based on an externally-supplied key + */ + +#include "internal.h" +#include "signature/SignatureValidator.h" + +#include +#include + +using namespace xmlsignature; +using namespace xmltooling; +using namespace std; + +void SignatureValidator::validate(const XMLObject* xmlObject) const +{ + const Signature* sigObj=dynamic_cast(xmlObject); + if (!sigObj) + throw ValidationException("Validator only applies to Signature objects."); + validate(sigObj); +} + +void SignatureValidator::validate(const Signature* sigObj) const +{ + DSIGSignature* sig=sigObj->getXMLSignature(); + if (!sig) + throw ValidationException("Signature does not exist yet."); + else if (!m_key && !m_resolver) + throw ValidationException("No KeyResolver or signing key set on Validator."); + + try { + XSECCryptoKey* key = m_key ? m_key->clone() : m_resolver->resolveKey(sig->getKeyInfoList()); + if (!key) + throw ValidationException("Unable to resolve signing key."); + sig->setSigningKey(key); + if (!sig->verify()) + throw ValidationException("Digital signature does not validate with the given key."); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + throw ValidationException(string("Caught an XMLSecurity exception verifying signature: ") + temp.get()); + } + catch(XSECCryptoException& e) { + throw ValidationException(string("Caught an XMLSecurity exception verifying signature: ") + e.getMsg()); + } +} diff --git a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp index 31f5743..4168149 100644 --- a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp +++ b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp @@ -1,409 +1,409 @@ -/* -* 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. - */ - -/** - * XMLSecSignatureImpl.cpp - * - * Signature class for XMLSec-based signature-handling - */ - -#include "internal.h" -#include "exceptions.h" -#include "impl/UnknownElement.h" -#include "signature/KeyInfo.h" -#include "signature/Signature.h" -#include "util/NDC.h" -#include "util/XMLConstants.h" -#include "util/XMLHelper.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace xmlsignature; -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmlsignature { - - class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature - { - public: - XMLSecSignatureImpl() : UnknownElementImpl(XMLConstants::XMLSIG_NS, Signature::LOCAL_NAME, XMLConstants::XMLSIG_PREFIX), - m_signature(NULL), m_c14n(NULL), m_sm(NULL), m_key(NULL), m_keyInfo(NULL), m_reference(NULL) {} - virtual ~XMLSecSignatureImpl(); - - void releaseDOM() const; - void releaseChildrenDOM(bool propagateRelease=true) const { - if (m_keyInfo) { - m_keyInfo->releaseDOM(); - if (propagateRelease) - m_keyInfo->releaseChildrenDOM(); - } - } - XMLObject* clone() const; - Signature* cloneSignature() const; - - DOMElement* marshall(DOMDocument* document=NULL, const vector* sigs=NULL) const; - DOMElement* marshall(DOMElement* parentElement, const vector* sigs=NULL) const; - XMLObject* unmarshall(DOMElement* element, bool bindDocument=false); - - // Getters - const XMLCh* getCanonicalizationMethod() const { return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC; } - const XMLCh* getSignatureAlgorithm() const { return m_sm ? m_sm : DSIGConstants::s_unicodeStrURIRSA_SHA1; } - KeyInfo* getKeyInfo() const { return m_keyInfo; } - ContentReference* getContentReference() const { return m_reference; } - DSIGSignature* getXMLSignature() const { return m_signature; } - - // Setters - void setCanonicalizationMethod(const XMLCh* c14n) { m_c14n = prepareForAssignment(m_c14n,c14n); } - void setSignatureAlgorithm(const XMLCh* sm) { m_sm = prepareForAssignment(m_sm,sm); } - void setSigningKey(XSECCryptoKey* signingKey) { - delete m_key; - m_key=signingKey; - } - void setKeyInfo(KeyInfo* keyInfo) { - prepareForAssignment(m_keyInfo, keyInfo); - m_keyInfo=keyInfo; - } - void setContentReference(ContentReference* reference) { - delete m_reference; - m_reference=reference; - } - - void sign(); - - private: - mutable DSIGSignature* m_signature; - XMLCh* m_c14n; - XMLCh* m_sm; - XSECCryptoKey* m_key; - KeyInfo* m_keyInfo; - ContentReference* m_reference; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -XMLSecSignatureImpl::~XMLSecSignatureImpl() -{ - // Release the associated signature. - if (m_signature) - XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature); - - XMLString::release(&m_c14n); - XMLString::release(&m_sm); - delete m_key; - delete m_keyInfo; - delete m_reference; -} - -void XMLSecSignatureImpl::releaseDOM() const -{ - if (getDOM()) { - // This should save off the DOM - UnknownElementImpl::releaseDOM(); - - // Release the associated signature. - if (m_signature) { - XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature); - m_signature=NULL; - } - } -} - -XMLObject* XMLSecSignatureImpl::clone() const -{ - return cloneSignature(); -} - -Signature* XMLSecSignatureImpl::cloneSignature() const -{ - XMLSecSignatureImpl* ret=new XMLSecSignatureImpl(); - - ret->m_c14n=XMLString::replicate(m_c14n); - ret->m_sm=XMLString::replicate(m_sm); - if (m_key) - ret->m_key=m_key->clone(); - if (m_keyInfo) - ret->m_keyInfo=m_keyInfo->cloneKeyInfo(); - - // If there's no XML locally, serialize this object into the new one, otherwise just copy it over. - if (m_xml.empty()) - serialize(ret->m_xml); - else - ret->m_xml=m_xml; - - return ret; -} - -void XMLSecSignatureImpl::sign() -{ - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature"); - log.debug("applying signature"); - - if (!m_signature) - throw SignatureException("Only a marshalled Signature object can be signed."); - else if (!m_key) - throw SignatureException("No signing key available for signature creation."); - else if (!m_reference) - throw SignatureException("No ContentReference object set for signature creation."); - - try { - log.debug("creating signature reference(s)"); - DSIGReferenceList* refs = m_signature->getReferenceList(); - while (refs && refs->getSize()) - delete refs->removeReference(0); - m_reference->createReferences(m_signature); - - log.debug("computing signature"); - m_signature->setSigningKey(m_key->clone()); - m_signature->sign(); - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + temp.get()); - } - catch(XSECCryptoException& e) { - throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + e.getMsg()); - } -} - -DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector* sigs) const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("marshall"); -#endif - - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature"); - log.debug("marshalling ds:Signature"); - - DOMElement* cachedDOM=getDOM(); - if (cachedDOM) { - if (!document || document==cachedDOM->getOwnerDocument()) { - log.debug("Signature has a usable cached DOM, reusing it"); - if (document) - setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM); - releaseParentDOM(true); - return cachedDOM; - } - - // We have a DOM but it doesn't match the document we were given. This both sucks and blows. - // Without an adoptNode option to maintain the child pointers, we have to either import the - // DOM while somehow reassigning all the nested references (which amounts to a complete - // *unmarshall* operation), or we just release the existing DOM and hope that we can get - // it back. This depends on all objects being able to preserve their DOM at all costs. - releaseChildrenDOM(true); - releaseDOM(); - } - - // If we get here, we didn't have a usable DOM. - bool bindDocument=false; - if (m_xml.empty()) { - // Fresh signature, so we just create an empty one. - log.debug("creating empty Signature element"); - if (!document) { - document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument(); - bindDocument=true; - } - m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature(); - m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX); - cachedDOM=m_signature->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm()); - } - else { - // We need to reparse the XML we saved off into a new DOM. - MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl"); - Wrapper4InputSource dsrc(&src,false); - log.debug("parsing Signature XML back into DOM tree"); - DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc); - if (document) { - // The caller insists on using his own document, so we now have to import the thing - // into it. Then we're just dumping the one we built. - log.debug("reimporting new DOM into caller-supplied document"); - cachedDOM=static_cast(document->importNode(internalDoc->getDocumentElement(), true)); - internalDoc->release(); - } - else { - // We just bind the document we built to the object as the result. - cachedDOM=static_cast(internalDoc->getDocumentElement()); - document=internalDoc; - bindDocument=true; - } - - // Now reload the signature from the DOM. - try { - m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( - document, cachedDOM - ); - m_signature->load(); - } - catch(XSECException& e) { - if (bindDocument) - document->release(); - auto_ptr_char temp(e.getMsg()); - throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get()); - } - catch(XSECCryptoException& e) { - if (bindDocument) - document->release(); - throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg()); - } - } - - // Marshall KeyInfo data. - if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) { - m_keyInfo->marshall(cachedDOM); - } - - // Recache the DOM and clear the serialized copy. - setDocumentElement(document, cachedDOM); - log.debug("caching DOM for Signature (document is %sbound)", bindDocument ? "" : "not "); - setDOM(cachedDOM, bindDocument); - releaseParentDOM(true); - m_xml.erase(); - return cachedDOM; -} - -DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vector* sigs) const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("marshall"); -#endif - - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature"); - log.debug("marshalling ds:Signature"); - - DOMElement* cachedDOM=getDOM(); - if (cachedDOM) { - if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { - log.debug("Signature has a usable cached DOM, reusing it"); - if (parentElement!=cachedDOM->getParentNode()) { - parentElement->appendChild(cachedDOM); - releaseParentDOM(true); - } - return cachedDOM; - } - - // We have a DOM but it doesn't match the document we were given. This both sucks and blows. - // Without an adoptNode option to maintain the child pointers, we have to either import the - // DOM while somehow reassigning all the nested references (which amounts to a complete - // *unmarshall* operation), or we just release the existing DOM and hope that we can get - // it back. This depends on all objects being able to preserve their DOM at all costs. - releaseChildrenDOM(true); - releaseDOM(); - } - - // If we get here, we didn't have a usable DOM. - if (m_xml.empty()) { - // Fresh signature, so we just create an empty one. - log.debug("creating empty Signature element"); - m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature(); - m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX); - cachedDOM=m_signature->createBlankSignature( - parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm() - ); - } - else { - MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl"); - Wrapper4InputSource dsrc(&src,false); - log.debug("parsing XML back into DOM tree"); - DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc); - - log.debug("reimporting new DOM into caller-supplied document"); - cachedDOM=static_cast(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(),true)); - internalDoc->release(); - - // Now reload the signature from the DOM. - try { - m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( - parentElement->getOwnerDocument(), cachedDOM - ); - m_signature->load(); - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get()); - } - catch(XSECCryptoException& e) { - throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg()); - } - } - - // Marshall KeyInfo data. - if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) { - m_keyInfo->marshall(cachedDOM); - } - - // Recache the DOM and clear the serialized copy. - parentElement->appendChild(cachedDOM); - log.debug("caching DOM for Signature"); - setDOM(cachedDOM, false); - releaseParentDOM(true); - m_xml.erase(); - return cachedDOM; -} - -XMLObject* XMLSecSignatureImpl::unmarshall(DOMElement* element, bool bindDocument) -{ - Category::getInstance(XMLTOOLING_LOGCAT".Signature").debug("unmarshalling ds:Signature"); - - try { - m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( - element->getOwnerDocument(), element - ); - m_signature->load(); - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get()); - } - catch(XSECCryptoException& e) { - throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg()); - } - - setDOM(element, bindDocument); - return this; -} - -Signature* SignatureBuilder::buildObject( - const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType - ) const -{ - if (!XMLString::equals(nsURI,XMLConstants::XMLSIG_NS) || !XMLString::equals(localName,Signature::LOCAL_NAME)) - throw XMLObjectException("XMLSecSignatureBuilder requires standard Signature element name."); - return buildObject(); -} - -Signature* SignatureBuilder::buildObject() const -{ - return new XMLSecSignatureImpl(); -} - -const XMLCh Signature::LOCAL_NAME[] = UNICODE_LITERAL_9(S,i,g,n,a,t,u,r,e); +/* +* 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. + */ + +/** + * XMLSecSignatureImpl.cpp + * + * Signature class for XMLSec-based signature-handling + */ + +#include "internal.h" +#include "exceptions.h" +#include "impl/UnknownElement.h" +#include "signature/KeyInfo.h" +#include "signature/Signature.h" +#include "util/NDC.h" +#include "util/XMLConstants.h" +#include "util/XMLHelper.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace xmlsignature; +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmlsignature { + + class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature + { + public: + XMLSecSignatureImpl() : UnknownElementImpl(XMLConstants::XMLSIG_NS, Signature::LOCAL_NAME, XMLConstants::XMLSIG_PREFIX), + m_signature(NULL), m_c14n(NULL), m_sm(NULL), m_key(NULL), m_keyInfo(NULL), m_reference(NULL) {} + virtual ~XMLSecSignatureImpl(); + + void releaseDOM() const; + void releaseChildrenDOM(bool propagateRelease=true) const { + if (m_keyInfo) { + m_keyInfo->releaseDOM(); + if (propagateRelease) + m_keyInfo->releaseChildrenDOM(); + } + } + XMLObject* clone() const; + Signature* cloneSignature() const; + + DOMElement* marshall(DOMDocument* document=NULL, const vector* sigs=NULL) const; + DOMElement* marshall(DOMElement* parentElement, const vector* sigs=NULL) const; + XMLObject* unmarshall(DOMElement* element, bool bindDocument=false); + + // Getters + const XMLCh* getCanonicalizationMethod() const { return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC; } + const XMLCh* getSignatureAlgorithm() const { return m_sm ? m_sm : DSIGConstants::s_unicodeStrURIRSA_SHA1; } + KeyInfo* getKeyInfo() const { return m_keyInfo; } + ContentReference* getContentReference() const { return m_reference; } + DSIGSignature* getXMLSignature() const { return m_signature; } + + // Setters + void setCanonicalizationMethod(const XMLCh* c14n) { m_c14n = prepareForAssignment(m_c14n,c14n); } + void setSignatureAlgorithm(const XMLCh* sm) { m_sm = prepareForAssignment(m_sm,sm); } + void setSigningKey(XSECCryptoKey* signingKey) { + delete m_key; + m_key=signingKey; + } + void setKeyInfo(KeyInfo* keyInfo) { + prepareForAssignment(m_keyInfo, keyInfo); + m_keyInfo=keyInfo; + } + void setContentReference(ContentReference* reference) { + delete m_reference; + m_reference=reference; + } + + void sign(); + + private: + mutable DSIGSignature* m_signature; + XMLCh* m_c14n; + XMLCh* m_sm; + XSECCryptoKey* m_key; + KeyInfo* m_keyInfo; + ContentReference* m_reference; + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +XMLSecSignatureImpl::~XMLSecSignatureImpl() +{ + // Release the associated signature. + if (m_signature) + XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature); + + XMLString::release(&m_c14n); + XMLString::release(&m_sm); + delete m_key; + delete m_keyInfo; + delete m_reference; +} + +void XMLSecSignatureImpl::releaseDOM() const +{ + if (getDOM()) { + // This should save off the DOM + UnknownElementImpl::releaseDOM(); + + // Release the associated signature. + if (m_signature) { + XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature); + m_signature=NULL; + } + } +} + +XMLObject* XMLSecSignatureImpl::clone() const +{ + return cloneSignature(); +} + +Signature* XMLSecSignatureImpl::cloneSignature() const +{ + XMLSecSignatureImpl* ret=new XMLSecSignatureImpl(); + + ret->m_c14n=XMLString::replicate(m_c14n); + ret->m_sm=XMLString::replicate(m_sm); + if (m_key) + ret->m_key=m_key->clone(); + if (m_keyInfo) + ret->m_keyInfo=m_keyInfo->cloneKeyInfo(); + + // If there's no XML locally, serialize this object into the new one, otherwise just copy it over. + if (m_xml.empty()) + serialize(ret->m_xml); + else + ret->m_xml=m_xml; + + return ret; +} + +void XMLSecSignatureImpl::sign() +{ + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature"); + log.debug("applying signature"); + + if (!m_signature) + throw SignatureException("Only a marshalled Signature object can be signed."); + else if (!m_key) + throw SignatureException("No signing key available for signature creation."); + else if (!m_reference) + throw SignatureException("No ContentReference object set for signature creation."); + + try { + log.debug("creating signature reference(s)"); + DSIGReferenceList* refs = m_signature->getReferenceList(); + while (refs && refs->getSize()) + delete refs->removeReference(0); + m_reference->createReferences(m_signature); + + log.debug("computing signature"); + m_signature->setSigningKey(m_key->clone()); + m_signature->sign(); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + temp.get()); + } + catch(XSECCryptoException& e) { + throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + e.getMsg()); + } +} + +DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector* sigs) const +{ +#ifdef _DEBUG + xmltooling::NDC ndc("marshall"); +#endif + + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature"); + log.debug("marshalling ds:Signature"); + + DOMElement* cachedDOM=getDOM(); + if (cachedDOM) { + if (!document || document==cachedDOM->getOwnerDocument()) { + log.debug("Signature has a usable cached DOM, reusing it"); + if (document) + setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM); + releaseParentDOM(true); + return cachedDOM; + } + + // We have a DOM but it doesn't match the document we were given. This both sucks and blows. + // Without an adoptNode option to maintain the child pointers, we have to either import the + // DOM while somehow reassigning all the nested references (which amounts to a complete + // *unmarshall* operation), or we just release the existing DOM and hope that we can get + // it back. This depends on all objects being able to preserve their DOM at all costs. + releaseChildrenDOM(true); + releaseDOM(); + } + + // If we get here, we didn't have a usable DOM. + bool bindDocument=false; + if (m_xml.empty()) { + // Fresh signature, so we just create an empty one. + log.debug("creating empty Signature element"); + if (!document) { + document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument(); + bindDocument=true; + } + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature(); + m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX); + cachedDOM=m_signature->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm()); + } + else { + // We need to reparse the XML we saved off into a new DOM. + MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl"); + Wrapper4InputSource dsrc(&src,false); + log.debug("parsing Signature XML back into DOM tree"); + DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc); + if (document) { + // The caller insists on using his own document, so we now have to import the thing + // into it. Then we're just dumping the one we built. + log.debug("reimporting new DOM into caller-supplied document"); + cachedDOM=static_cast(document->importNode(internalDoc->getDocumentElement(), true)); + internalDoc->release(); + } + else { + // We just bind the document we built to the object as the result. + cachedDOM=static_cast(internalDoc->getDocumentElement()); + document=internalDoc; + bindDocument=true; + } + + // Now reload the signature from the DOM. + try { + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( + document, cachedDOM + ); + m_signature->load(); + } + catch(XSECException& e) { + if (bindDocument) + document->release(); + auto_ptr_char temp(e.getMsg()); + throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get()); + } + catch(XSECCryptoException& e) { + if (bindDocument) + document->release(); + throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg()); + } + } + + // Marshall KeyInfo data. + if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) { + m_keyInfo->marshall(cachedDOM); + } + + // Recache the DOM and clear the serialized copy. + setDocumentElement(document, cachedDOM); + log.debug("caching DOM for Signature (document is %sbound)", bindDocument ? "" : "not "); + setDOM(cachedDOM, bindDocument); + releaseParentDOM(true); + m_xml.erase(); + return cachedDOM; +} + +DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vector* sigs) const +{ +#ifdef _DEBUG + xmltooling::NDC ndc("marshall"); +#endif + + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature"); + log.debug("marshalling ds:Signature"); + + DOMElement* cachedDOM=getDOM(); + if (cachedDOM) { + if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { + log.debug("Signature has a usable cached DOM, reusing it"); + if (parentElement!=cachedDOM->getParentNode()) { + parentElement->appendChild(cachedDOM); + releaseParentDOM(true); + } + return cachedDOM; + } + + // We have a DOM but it doesn't match the document we were given. This both sucks and blows. + // Without an adoptNode option to maintain the child pointers, we have to either import the + // DOM while somehow reassigning all the nested references (which amounts to a complete + // *unmarshall* operation), or we just release the existing DOM and hope that we can get + // it back. This depends on all objects being able to preserve their DOM at all costs. + releaseChildrenDOM(true); + releaseDOM(); + } + + // If we get here, we didn't have a usable DOM. + if (m_xml.empty()) { + // Fresh signature, so we just create an empty one. + log.debug("creating empty Signature element"); + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature(); + m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX); + cachedDOM=m_signature->createBlankSignature( + parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm() + ); + } + else { + MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl"); + Wrapper4InputSource dsrc(&src,false); + log.debug("parsing XML back into DOM tree"); + DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc); + + log.debug("reimporting new DOM into caller-supplied document"); + cachedDOM=static_cast(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(),true)); + internalDoc->release(); + + // Now reload the signature from the DOM. + try { + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( + parentElement->getOwnerDocument(), cachedDOM + ); + m_signature->load(); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get()); + } + catch(XSECCryptoException& e) { + throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg()); + } + } + + // Marshall KeyInfo data. + if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) { + m_keyInfo->marshall(cachedDOM); + } + + // Recache the DOM and clear the serialized copy. + parentElement->appendChild(cachedDOM); + log.debug("caching DOM for Signature"); + setDOM(cachedDOM, false); + releaseParentDOM(true); + m_xml.erase(); + return cachedDOM; +} + +XMLObject* XMLSecSignatureImpl::unmarshall(DOMElement* element, bool bindDocument) +{ + Category::getInstance(XMLTOOLING_LOGCAT".Signature").debug("unmarshalling ds:Signature"); + + try { + m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( + element->getOwnerDocument(), element + ); + m_signature->load(); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get()); + } + catch(XSECCryptoException& e) { + throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg()); + } + + setDOM(element, bindDocument); + return this; +} + +Signature* SignatureBuilder::buildObject( + const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType + ) const +{ + if (!XMLString::equals(nsURI,XMLConstants::XMLSIG_NS) || !XMLString::equals(localName,Signature::LOCAL_NAME)) + throw XMLObjectException("XMLSecSignatureBuilder requires standard Signature element name."); + return buildObject(); +} + +Signature* SignatureBuilder::buildObject() const +{ + return new XMLSecSignatureImpl(); +} + +const XMLCh Signature::LOCAL_NAME[] = UNICODE_LITERAL_9(S,i,g,n,a,t,u,r,e); diff --git a/xmltooling/soap/impl/SOAPImpl.cpp b/xmltooling/soap/impl/SOAPImpl.cpp index eefa5a6..53d743f 100644 --- a/xmltooling/soap/impl/SOAPImpl.cpp +++ b/xmltooling/soap/impl/SOAPImpl.cpp @@ -348,8 +348,8 @@ namespace { } EnvelopeImpl(const EnvelopeImpl& src) - : AbstractXMLObject(src), AbstractComplexElement(src), - AbstractAttributeExtensibleXMLObject(src), AbstractDOMCachingXMLObject(src) { + : AbstractXMLObject(src), AbstractAttributeExtensibleXMLObject(src), + AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) { init(); if (src.getHeader()) setHeader(src.getHeader()->cloneHeader()); diff --git a/xmltooling/unicode.cpp b/xmltooling/unicode.cpp index 1d95fb7..dd8a45e 100644 --- a/xmltooling/unicode.cpp +++ b/xmltooling/unicode.cpp @@ -1,59 +1,59 @@ -/* - * 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. - */ - -/** - * unicode.cpp - * - * Helper classes and types for manipulating Unicode - */ - -#include "internal.h" -#include "unicode.h" - -#include -#include - -static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDigit_8, chNull }; - -char* xmltooling::toUTF8(const XMLCh* src) -{ - unsigned int eaten; - unsigned int srclen=XMLString::stringLen(src); - XMLUTF8Transcoder t(UTF8, srclen*4 + 1); - char* buf=new char[srclen*4 + 1]; - memset(buf,0,srclen*4 + 1); - t.transcodeTo( - src,srclen, - reinterpret_cast(buf),srclen*4, - eaten,XMLTranscoder::UnRep_RepChar); - return buf; -} - -XMLCh* xmltooling::fromUTF8(const char* src) -{ - unsigned int eaten; - unsigned int srclen=strlen(src); - XMLUTF8Transcoder t(UTF8, srclen + 1); - XMLCh* buf=new XMLCh[srclen + 1]; - unsigned char* sizes=new unsigned char[srclen]; - memset(buf,0,(srclen+1)*sizeof(XMLCh)); - t.transcodeFrom( - reinterpret_cast(src),srclen, - buf,srclen, - eaten,sizes); - delete[] sizes; - return buf; -} +/* + * 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. + */ + +/** + * unicode.cpp + * + * Helper classes and types for manipulating Unicode + */ + +#include "internal.h" +#include "unicode.h" + +#include +#include + +static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDigit_8, chNull }; + +char* xmltooling::toUTF8(const XMLCh* src) +{ + unsigned int eaten; + unsigned int srclen=XMLString::stringLen(src); + XMLUTF8Transcoder t(UTF8, srclen*4 + 1); + char* buf=new char[srclen*4 + 1]; + memset(buf,0,srclen*4 + 1); + t.transcodeTo( + src,srclen, + reinterpret_cast(buf),srclen*4, + eaten,XMLTranscoder::UnRep_RepChar); + return buf; +} + +XMLCh* xmltooling::fromUTF8(const char* src) +{ + unsigned int eaten; + unsigned int srclen=strlen(src); + XMLUTF8Transcoder t(UTF8, srclen + 1); + XMLCh* buf=new XMLCh[srclen + 1]; + unsigned char* sizes=new unsigned char[srclen]; + memset(buf,0,(srclen+1)*sizeof(XMLCh)); + t.transcodeFrom( + reinterpret_cast(src),srclen, + buf,srclen, + eaten,sizes); + delete[] sizes; + return buf; +} diff --git a/xmltooling/unicode.h b/xmltooling/unicode.h index 50e78f4..b4bd111 100644 --- a/xmltooling/unicode.h +++ b/xmltooling/unicode.h @@ -1,150 +1,150 @@ -/* - * 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 unicode.h - * - * Helper classes and types for manipulating Unicode - */ - -#if !defined(__xmltooling_unicode_h__) -#define __xmltooling_unicode_h__ - -#include -#include -#include - -using namespace xercesc; - -namespace xmltooling { - - #ifdef HAVE_GOOD_STL - /** - * An STL string type that supports 16-bit Unicode. - * Most compilers support this, but various versions of gcc3 do not. - */ - typedef std::basic_string xstring; - #endif - - /** - * Transcodes a 16-bit Unicode string into UTF-8. - * @param src the 16-bit string to transcode - * @return a UTF-8 string allocated by the Xerces memory manager - */ - extern XMLTOOL_API char* toUTF8(const XMLCh* src); - - /** - * Transcodes a UTF-8 string into 16-bit Unicode. - * @param src the UTF-8 string to transcode - * @return a 16-bit Unicode string allocated by the Xerces memory manager - */ - extern XMLTOOL_API XMLCh* fromUTF8(const char* src); - - /** - * A minimal auto_ptr-like class that can copy or transcode a buffer into - * the local code page and free the result automatically. - * - * Needed because a standard auto_ptr would use delete on the resulting - * pointer. - */ - class XMLTOOL_API auto_ptr_char - { - public: - /** - * Constructor transcodes a 16-bit Unicode string into the local code page (NOT UTF-8) and wraps the result. - * @param src the 16-bit string to transcode and wrap - * @param trim trims leading/trailing whitespace from the result (defaults to true) - */ - auto_ptr_char(const XMLCh* src, bool trim=true) : m_buf(XMLString::transcode(src)) {if (trim && m_buf) XMLString::trim(m_buf);} - - /** - * Constructor copies a local code page (NOT UTF-8) string and wraps the result. - * @param src the local string to copy and wrap - * @param trim trims leading/trailing whitespace from the result (defaults to true) - */ - auto_ptr_char(const char* src, bool trim=true) : m_buf(XMLString::replicate(src)) {if (trim && m_buf) XMLString::trim(m_buf);} - - /** - * Destructor frees the wrapped buffer using the Xerces memory manager. - */ - ~auto_ptr_char() { XMLString::release(&m_buf); } - - /** - * Returns the wrapped buffer. - * @return a null-terminated local code page string - */ - const char* get() const { return m_buf; } - - /** - * Returns the wrapped buffer and transfers ownership of it to the caller. - * @return a null-terminated local code page string - */ - char* release() { char* temp=m_buf; m_buf=NULL; return temp; } - - private: - char* m_buf; - MAKE_NONCOPYABLE(auto_ptr_char); - }; - - /** - * A minimal auto_ptr-like class that can copy or transcode a buffer into - * 16-bit Unicode and free the result automatically. - * - * Needed because a standard auto_ptr would use delete on the resulting - * pointer. - */ - class XMLTOOL_API auto_ptr_XMLCh - { - public: - /** - * Constructor transcodes a local code page (NOT UTF-8) string into 16-bit Unicode and wraps the result. - * @param src the local string to transcode and wrap - * @param trim trims leading/trailing whitespace from the result (defaults to true) - */ - auto_ptr_XMLCh(const char* src, bool trim=true) : m_buf(XMLString::transcode(src)) {if (trim && m_buf) XMLString::trim(m_buf);} - - /** - * Constructor copies a 16-bit Unicode string and wraps the result. - * @param src the Unicode string to copy and wrap - * @param trim trims leading/trailing whitespace from the result (defaults to true) - */ - auto_ptr_XMLCh(const XMLCh* src, bool trim=true) : m_buf(XMLString::replicate(src)) {if (trim && m_buf) XMLString::trim(m_buf);} - - /** - * Destructor frees the wrapped buffer using the Xerces memory manager. - */ - ~auto_ptr_XMLCh() { XMLString::release(&m_buf); } - - /** - * Returns the wrapped buffer. - * @return a null-terminated Unicode string - */ - const XMLCh* get() const { return m_buf; } - - /** - * Returns the wrapped buffer and transfers ownership of it to the caller. - * @return a null-terminated Unicode string - */ - XMLCh* release() { XMLCh* temp=m_buf; m_buf=NULL; return temp; } - - private: - XMLCh* m_buf; - MAKE_NONCOPYABLE(auto_ptr_XMLCh); - }; - -}; - -#endif /* __xmltooling_unicode_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 unicode.h + * + * Helper classes and types for manipulating Unicode + */ + +#if !defined(__xmltooling_unicode_h__) +#define __xmltooling_unicode_h__ + +#include +#include +#include + +using namespace xercesc; + +namespace xmltooling { + + #ifdef HAVE_GOOD_STL + /** + * An STL string type that supports 16-bit Unicode. + * Most compilers support this, but various versions of gcc3 do not. + */ + typedef std::basic_string xstring; + #endif + + /** + * Transcodes a 16-bit Unicode string into UTF-8. + * @param src the 16-bit string to transcode + * @return a UTF-8 string allocated by the Xerces memory manager + */ + extern XMLTOOL_API char* toUTF8(const XMLCh* src); + + /** + * Transcodes a UTF-8 string into 16-bit Unicode. + * @param src the UTF-8 string to transcode + * @return a 16-bit Unicode string allocated by the Xerces memory manager + */ + extern XMLTOOL_API XMLCh* fromUTF8(const char* src); + + /** + * A minimal auto_ptr-like class that can copy or transcode a buffer into + * the local code page and free the result automatically. + * + * Needed because a standard auto_ptr would use delete on the resulting + * pointer. + */ + class XMLTOOL_API auto_ptr_char + { + public: + /** + * Constructor transcodes a 16-bit Unicode string into the local code page (NOT UTF-8) and wraps the result. + * @param src the 16-bit string to transcode and wrap + * @param trim trims leading/trailing whitespace from the result (defaults to true) + */ + auto_ptr_char(const XMLCh* src, bool trim=true) : m_buf(XMLString::transcode(src)) {if (trim && m_buf) XMLString::trim(m_buf);} + + /** + * Constructor copies a local code page (NOT UTF-8) string and wraps the result. + * @param src the local string to copy and wrap + * @param trim trims leading/trailing whitespace from the result (defaults to true) + */ + auto_ptr_char(const char* src, bool trim=true) : m_buf(XMLString::replicate(src)) {if (trim && m_buf) XMLString::trim(m_buf);} + + /** + * Destructor frees the wrapped buffer using the Xerces memory manager. + */ + ~auto_ptr_char() { XMLString::release(&m_buf); } + + /** + * Returns the wrapped buffer. + * @return a null-terminated local code page string + */ + const char* get() const { return m_buf; } + + /** + * Returns the wrapped buffer and transfers ownership of it to the caller. + * @return a null-terminated local code page string + */ + char* release() { char* temp=m_buf; m_buf=NULL; return temp; } + + private: + char* m_buf; + MAKE_NONCOPYABLE(auto_ptr_char); + }; + + /** + * A minimal auto_ptr-like class that can copy or transcode a buffer into + * 16-bit Unicode and free the result automatically. + * + * Needed because a standard auto_ptr would use delete on the resulting + * pointer. + */ + class XMLTOOL_API auto_ptr_XMLCh + { + public: + /** + * Constructor transcodes a local code page (NOT UTF-8) string into 16-bit Unicode and wraps the result. + * @param src the local string to transcode and wrap + * @param trim trims leading/trailing whitespace from the result (defaults to true) + */ + auto_ptr_XMLCh(const char* src, bool trim=true) : m_buf(XMLString::transcode(src)) {if (trim && m_buf) XMLString::trim(m_buf);} + + /** + * Constructor copies a 16-bit Unicode string and wraps the result. + * @param src the Unicode string to copy and wrap + * @param trim trims leading/trailing whitespace from the result (defaults to true) + */ + auto_ptr_XMLCh(const XMLCh* src, bool trim=true) : m_buf(XMLString::replicate(src)) {if (trim && m_buf) XMLString::trim(m_buf);} + + /** + * Destructor frees the wrapped buffer using the Xerces memory manager. + */ + ~auto_ptr_XMLCh() { XMLString::release(&m_buf); } + + /** + * Returns the wrapped buffer. + * @return a null-terminated Unicode string + */ + const XMLCh* get() const { return m_buf; } + + /** + * Returns the wrapped buffer and transfers ownership of it to the caller. + * @return a null-terminated Unicode string + */ + XMLCh* release() { XMLCh* temp=m_buf; m_buf=NULL; return temp; } + + private: + XMLCh* m_buf; + MAKE_NONCOPYABLE(auto_ptr_XMLCh); + }; + +}; + +#endif /* __xmltooling_unicode_h__ */ diff --git a/xmltooling/util/DateTime.cpp b/xmltooling/util/DateTime.cpp index 7877c50..6e27cb2 100644 --- a/xmltooling/util/DateTime.cpp +++ b/xmltooling/util/DateTime.cpp @@ -1,1621 +1,1621 @@ -/* - * 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. - */ - -/** - * DateTime.cpp - * - * Manipulation of XML date/time data. - */ - -/* - * This is mostly copied from Xerces-C, but they don't seem inclined to produce a usable - * class, so I had to incorporate my own version of it for now. I can't inherit it - * since the fields I need are private. - */ - -#include "internal.h" -#include "util/DateTime.h" - -#ifndef WIN32 -# include -#endif - -#include -#include -#include - -using namespace xmltooling; -using namespace std; - -// -// constants used to process raw data (fBuffer) -// -// [-]{CCYY-MM-DD}'T'{HH:MM:SS.MS}['Z'] -// [{+|-}hh:mm'] -// - -static const XMLCh DURATION_STARTER = chLatin_P; // 'P' -static const XMLCh DURATION_Y = chLatin_Y; // 'Y' -static const XMLCh DURATION_M = chLatin_M; // 'M' -static const XMLCh DURATION_D = chLatin_D; // 'D' -static const XMLCh DURATION_H = chLatin_H; // 'H' -static const XMLCh DURATION_S = chLatin_S; // 'S' - -static const XMLCh DATE_SEPARATOR = chDash; // '-' -static const XMLCh TIME_SEPARATOR = chColon; // ':' -static const XMLCh TIMEZONE_SEPARATOR = chColon; // ':' -static const XMLCh DATETIME_SEPARATOR = chLatin_T; // 'T' -static const XMLCh MILISECOND_SEPARATOR = chPeriod; // '.' - -static const XMLCh UTC_STD_CHAR = chLatin_Z; // 'Z' -static const XMLCh UTC_POS_CHAR = chPlus; // '+' -static const XMLCh UTC_NEG_CHAR = chDash; // '-' - -static const XMLCh UTC_SET[] = {UTC_STD_CHAR //"Z+-" - , UTC_POS_CHAR - , UTC_NEG_CHAR - , chNull}; - -static const int YMD_MIN_SIZE = 10; // CCYY-MM-DD -static const int YMONTH_MIN_SIZE = 7; // CCYY_MM -static const int TIME_MIN_SIZE = 8; // hh:mm:ss -static const int TIMEZONE_SIZE = 5; // hh:mm -static const int DAY_SIZE = 5; // ---DD -//static const int MONTH_SIZE = 6; // --MM-- -static const int MONTHDAY_SIZE = 7; // --MM-DD -static const int NOT_FOUND = -1; - -//define constants to be used in assigning default values for -//all date/time excluding duration -static const int YEAR_DEFAULT = 2000; -static const int MONTH_DEFAULT = 01; -static const int DAY_DEFAULT = 15; - -// order-relation on duration is a partial order. The dates below are used to -// for comparison of 2 durations, based on the fact that -// duration x and y is x<=y iff s+x<=s+y -// see 3.2.6 duration W3C schema datatype specs -// -// the dates are in format: {CCYY,MM,DD, H, S, M, MS, timezone} -const int DateTime::DATETIMES[][TOTAL_SIZE] = -{ - {1696, 9, 1, 0, 0, 0, 0, UTC_STD}, - {1697, 2, 1, 0, 0, 0, 0, UTC_STD}, - {1903, 3, 1, 0, 0, 0, 0, UTC_STD}, - {1903, 7, 1, 0, 0, 0, 0, UTC_STD} -}; - -// --------------------------------------------------------------------------- -// local methods -// --------------------------------------------------------------------------- -static inline int fQuotient(int a, int b) -{ - div_t div_result = div(a, b); - return div_result.quot; -} - -static inline int fQuotient(int temp, int low, int high) -{ - return fQuotient(temp - low, high - low); -} - -static inline int mod(int a, int b, int quotient) -{ - return (a - quotient*b) ; -} - -static inline int modulo (int temp, int low, int high) -{ - //modulo(a - low, high - low) + low - int a = temp - low; - int b = high - low; - return (mod (a, b, fQuotient(a, b)) + low) ; -} - -static inline bool isLeapYear(int year) -{ - return((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))); -} - -static int maxDayInMonthFor(int year, int month) -{ - - if ( month == 4 || month == 6 || month == 9 || month == 11 ) - { - return 30; - } - else if ( month==2 ) - { - if ( isLeapYear(year) ) - return 29; - else - return 28; - } - else - { - return 31; - } - -} - -// --------------------------------------------------------------------------- -// static methods : for duration -// --------------------------------------------------------------------------- -/** - * Compares 2 given durations. (refer to W3C Schema Datatypes "3.2.6 duration") - * - * 3.2.6.2 Order relation on duration - * - * In general, the order-relation on duration is a partial order since there is no - * determinate relationship between certain durations such as one month (P1M) and 30 days (P30D). - * The order-relation of two duration values x and y is x < y iff s+x < s+y for each qualified - * dateTime s in the list below. - * - * These values for s cause the greatest deviations in the addition of dateTimes and durations - * - **/ -int DateTime::compare(const DateTime* const pDate1 - , const DateTime* const pDate2 - , bool strict) -{ - //REVISIT: this is unoptimazed vs of comparing 2 durations - // Algorithm is described in 3.2.6.2 W3C Schema Datatype specs - // - - int resultA, resultB = XMLDateTime::INDETERMINATE; - - //try and see if the objects are equal - if ( (resultA = compareOrder(pDate1, pDate2)) == XMLDateTime::EQUAL) - return XMLDateTime::EQUAL; - - //long comparison algorithm is required - DateTime tempA, *pTempA = &tempA; - DateTime tempB, *pTempB = &tempB; - - addDuration(pTempA, pDate1, 0); - addDuration(pTempB, pDate2, 0); - resultA = compareOrder(pTempA, pTempB); - if ( resultA == XMLDateTime::INDETERMINATE ) - return XMLDateTime::INDETERMINATE; - - addDuration(pTempA, pDate1, 1); - addDuration(pTempB, pDate2, 1); - resultB = compareOrder(pTempA, pTempB); - resultA = compareResult(resultA, resultB, strict); - if ( resultA == XMLDateTime::INDETERMINATE ) - return XMLDateTime::INDETERMINATE; - - addDuration(pTempA, pDate1, 2); - addDuration(pTempB, pDate2, 2); - resultB = compareOrder(pTempA, pTempB); - resultA = compareResult(resultA, resultB, strict); - if ( resultA == XMLDateTime::INDETERMINATE ) - return XMLDateTime::INDETERMINATE; - - addDuration(pTempA, pDate1, 3); - addDuration(pTempB, pDate2, 3); - resultB = compareOrder(pTempA, pTempB); - resultA = compareResult(resultA, resultB, strict); - - return resultA; - -} - -// -// Form a new DateTime with duration and baseDate array -// Note: C++ Java -// fNewDate duration -// fDuration date -// - -void DateTime::addDuration(DateTime* fNewDate - , const DateTime* const fDuration - , int index) - -{ - - //REVISIT: some code could be shared between normalize() and this method, - // however is it worth moving it? The structures are different... - // - - fNewDate->reset(); - //add months (may be modified additionaly below) - int temp = DATETIMES[index][Month] + fDuration->fValue[Month]; - fNewDate->fValue[Month] = modulo(temp, 1, 13); - int carry = fQuotient(temp, 1, 13); - - //add years (may be modified additionaly below) - fNewDate->fValue[CentYear] = - DATETIMES[index][CentYear] + fDuration->fValue[CentYear] + carry; - - //add seconds - temp = DATETIMES[index][Second] + fDuration->fValue[Second]; - carry = fQuotient (temp, 60); - fNewDate->fValue[Second] = mod(temp, 60, carry); - - //add minutes - temp = DATETIMES[index][Minute] + fDuration->fValue[Minute] + carry; - carry = fQuotient(temp, 60); - fNewDate->fValue[Minute] = mod(temp, 60, carry); - - //add hours - temp = DATETIMES[index][Hour] + fDuration->fValue[Hour] + carry; - carry = fQuotient(temp, 24); - fNewDate->fValue[Hour] = mod(temp, 24, carry); - - fNewDate->fValue[Day] = - DATETIMES[index][Day] + fDuration->fValue[Day] + carry; - - while ( true ) - { - temp = maxDayInMonthFor(fNewDate->fValue[CentYear], fNewDate->fValue[Month]); - if ( fNewDate->fValue[Day] < 1 ) - { //original fNewDate was negative - fNewDate->fValue[Day] += - maxDayInMonthFor(fNewDate->fValue[CentYear], fNewDate->fValue[Month]-1); - carry = -1; - } - else if ( fNewDate->fValue[Day] > temp ) - { - fNewDate->fValue[Day] -= temp; - carry = 1; - } - else - { - break; - } - - temp = fNewDate->fValue[Month] + carry; - fNewDate->fValue[Month] = modulo(temp, 1, 13); - fNewDate->fValue[CentYear] += fQuotient(temp, 1, 13); - } - - //fNewDate->fValue[utc] = UTC_STD_CHAR; - fNewDate->fValue[utc] = UTC_STD; -} - -int DateTime::compareResult(int resultA - , int resultB - , bool strict) -{ - - if ( resultB == XMLDateTime::INDETERMINATE ) - { - return XMLDateTime::INDETERMINATE; - } - else if ( (resultA != resultB) && - strict ) - { - return XMLDateTime::INDETERMINATE; - } - else if ( (resultA != resultB) && - !strict ) - { - if ( (resultA != XMLDateTime::EQUAL) && - (resultB != XMLDateTime::EQUAL) ) - { - return XMLDateTime::INDETERMINATE; - } - else - { - return (resultA != XMLDateTime::EQUAL)? resultA : resultB; - } - } - - return resultA; - -} - -// --------------------------------------------------------------------------- -// static methods : for others -// --------------------------------------------------------------------------- -int DateTime::compare(const DateTime* const pDate1 - , const DateTime* const pDate2) -{ - - if (pDate1->fValue[utc] == pDate2->fValue[utc]) - { - return DateTime::compareOrder(pDate1, pDate2); - } - - int c1, c2; - - if ( pDate1->isNormalized()) - { - c1 = compareResult(pDate1, pDate2, false, UTC_POS); - c2 = compareResult(pDate1, pDate2, false, UTC_NEG); - return getRetVal(c1, c2); - } - else if ( pDate2->isNormalized()) - { - c1 = compareResult(pDate1, pDate2, true, UTC_POS); - c2 = compareResult(pDate1, pDate2, true, UTC_NEG); - return getRetVal(c1, c2); - } - - return XMLDateTime::INDETERMINATE; -} - -int DateTime::compareResult(const DateTime* const pDate1 - , const DateTime* const pDate2 - , bool set2Left - , int utc_type) -{ - DateTime tmpDate = (set2Left ? *pDate1 : *pDate2); - - tmpDate.fTimeZone[hh] = 14; - tmpDate.fTimeZone[mm] = 0; - tmpDate.fValue[utc] = utc_type; - tmpDate.normalize(); - - return (set2Left? DateTime::compareOrder(&tmpDate, pDate2) : - DateTime::compareOrder(pDate1, &tmpDate)); -} - -int DateTime::compareOrder(const DateTime* const lValue - , const DateTime* const rValue) - //, MemoryManager* const memMgr) -{ - // - // If any of the them is not normalized() yet, - // we need to do something here. - // - DateTime lTemp = *lValue; - DateTime rTemp = *rValue; - - lTemp.normalize(); - rTemp.normalize(); - - for ( int i = 0 ; i < TOTAL_SIZE; i++ ) - { - if ( lTemp.fValue[i] < rTemp.fValue[i] ) - { - return XMLDateTime::LESS_THAN; - } - else if ( lTemp.fValue[i] > rTemp.fValue[i] ) - { - return XMLDateTime::GREATER_THAN; - } - } - - if ( lTemp.fHasTime) - { - if ( lTemp.fMiliSecond < rTemp.fMiliSecond ) - { - return XMLDateTime::LESS_THAN; - } - else if ( lTemp.fMiliSecond > rTemp.fMiliSecond ) - { - return XMLDateTime::GREATER_THAN; - } - } - - return XMLDateTime::EQUAL; -} - -// --------------------------------------------------------------------------- -// ctor and dtor -// --------------------------------------------------------------------------- -DateTime::~DateTime() -{ - delete[] fBuffer; -} - -DateTime::DateTime() -: fStart(0) -, fEnd(0) -, fBufferMaxLen(0) -, fBuffer(0) -, fMiliSecond(0) -, fHasTime(false) -{ - reset(); -} - -DateTime::DateTime(const XMLCh* const aString) -: fStart(0) -, fEnd(0) -, fBufferMaxLen(0) -, fBuffer(0) -, fMiliSecond(0) -, fHasTime(false) -{ - setBuffer(aString); -} - -DateTime::DateTime(time_t epoch) -: fStart(0) -, fEnd(0) -, fBufferMaxLen(0) -, fBuffer(0) -, fMiliSecond(0) -, fHasTime(false) -{ -#ifndef HAVE_GMTIME_R - struct tm* ptime=gmtime(&epoch); -#else - struct tm res; - struct tm* ptime=gmtime_r(&epoch,&res); -#endif - char timebuf[32]; - strftime(timebuf,32,"%Y-%m-%dT%H:%M:%SZ",ptime); - auto_ptr_XMLCh timeptr(timebuf); - setBuffer(timeptr.get()); -} - -// ----------------------------------------------------------------------- -// Copy ctor and Assignment operators -// ----------------------------------------------------------------------- - -DateTime::DateTime(const DateTime &toCopy) -: fBufferMaxLen(0) -, fBuffer(0) -{ - copy(toCopy); -} - -DateTime& DateTime::operator=(const DateTime& rhs) -{ - if (this == &rhs) - return *this; - - copy(rhs); - return *this; -} - -// ----------------------------------------------------------------------- -// Implementation of Abstract Interface -// ----------------------------------------------------------------------- - -// -// We may simply return the handle to fBuffer -// -const XMLCh* DateTime::getRawData() const -{ - //assertBuffer(); - return fBuffer; -} - - -const XMLCh* DateTime::getFormattedString() const -{ - return getRawData(); -} - -int DateTime::getSign() const -{ - return 0; -} - -time_t DateTime::getEpoch() const -{ - struct tm t; - t.tm_sec=getSecond(); - t.tm_min=getMinute(); - t.tm_hour=getHour(); - t.tm_mday=getDay(); - t.tm_mon=getMonth()-1; - t.tm_year=getYear()-1900; - t.tm_isdst=0; -#if defined(HAVE_TIMEGM) - return timegm(&t); -#else - // Windows, and hopefully most others...? - return mktime(&t) - timezone; -#endif -} - -// --------------------------------------------------------------------------- -// Parsers -// --------------------------------------------------------------------------- - -// -// [-]{CCYY-MM-DD}'T'{HH:MM:SS.MS}[TimeZone] -// -void DateTime::parseDateTime() -{ - initParser(); - getDate(); - - //fStart is supposed to point to 'T' - if (fBuffer[fStart++] != DATETIME_SEPARATOR) - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_gDay_invalid - , fBuffer); - - getTime(); - validateDateTime(); - normalize(); - fHasTime = true; -} - -// -// [-]{CCYY-MM-DD}[TimeZone] -// -void DateTime::parseDate() -{ - initParser(); - getDate(); - parseTimeZone(); - validateDateTime(); - normalize(); -} - -void DateTime::parseTime() -{ - initParser(); - - // time initialize to default values - fValue[CentYear]= YEAR_DEFAULT; - fValue[Month] = MONTH_DEFAULT; - fValue[Day] = DAY_DEFAULT; - - getTime(); - - validateDateTime(); - normalize(); - fHasTime = true; -} - -// -// {---DD}[TimeZone] -// 01234 -// -void DateTime::parseDay() -{ - initParser(); - - if (fBuffer[0] != DATE_SEPARATOR || - fBuffer[1] != DATE_SEPARATOR || - fBuffer[2] != DATE_SEPARATOR ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_gDay_invalid - , fBuffer); - } - - //initialize values - fValue[CentYear] = YEAR_DEFAULT; - fValue[Month] = MONTH_DEFAULT; - fValue[Day] = parseInt(fStart+3, fStart+5); - - if ( DAY_SIZE < fEnd ) - { - int sign = findUTCSign(DAY_SIZE); - if ( sign < 0 ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_gDay_invalid - , fBuffer); - } - else - { - getTimeZone(sign); - } - } - - validateDateTime(); - normalize(); -} - -// -// {--MM--}[TimeZone] -// {--MM}[TimeZone] -// 012345 -// -void DateTime::parseMonth() -{ - initParser(); - - if (fBuffer[0] != DATE_SEPARATOR || - fBuffer[1] != DATE_SEPARATOR ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_gMth_invalid - , fBuffer); - } - - //set constants - fValue[CentYear] = YEAR_DEFAULT; - fValue[Day] = DAY_DEFAULT; - fValue[Month] = parseInt(2, 4); - - // REVISIT: allow both --MM and --MM-- now. - // need to remove the following lines to disallow --MM-- - // when the errata is officially in the rec. - fStart = 4; - if ( fEnd >= fStart+2 && fBuffer[fStart] == DATE_SEPARATOR && fBuffer[fStart+1] == DATE_SEPARATOR ) - { - fStart += 2; - } - - // - // parse TimeZone if any - // - if ( fStart < fEnd ) - { - int sign = findUTCSign(fStart); - if ( sign < 0 ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_gMth_invalid - , fBuffer); - } - else - { - getTimeZone(sign); - } - } - - validateDateTime(); - normalize(); -} - -// -//[-]{CCYY}[TimeZone] -// 0 1234 -// -void DateTime::parseYear() -{ - initParser(); - - // skip the first '-' and search for timezone - // - int sign = findUTCSign((fBuffer[0] == chDash) ? 1 : 0); - - if (sign == NOT_FOUND) - { - fValue[CentYear] = parseIntYear(fEnd); - } - else - { - fValue[CentYear] = parseIntYear(sign); - getTimeZone(sign); - } - - //initialize values - fValue[Month] = MONTH_DEFAULT; - fValue[Day] = DAY_DEFAULT; //java is 1 - - validateDateTime(); - normalize(); -} - -// -//{--MM-DD}[TimeZone] -// 0123456 -// -void DateTime::parseMonthDay() -{ - initParser(); - - if (fBuffer[0] != DATE_SEPARATOR || - fBuffer[1] != DATE_SEPARATOR || - fBuffer[4] != DATE_SEPARATOR ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_gMthDay_invalid - , fBuffer); - } - - - //initialize - fValue[CentYear] = YEAR_DEFAULT; - fValue[Month] = parseInt(2, 4); - fValue[Day] = parseInt(5, 7); - - if ( MONTHDAY_SIZE < fEnd ) - { - int sign = findUTCSign(MONTHDAY_SIZE); - if ( sign<0 ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_gMthDay_invalid - , fBuffer); - } - else - { - getTimeZone(sign); - } - } - - validateDateTime(); - normalize(); -} - -void DateTime::parseYearMonth() -{ - initParser(); - - // get date - getYearMonth(); - fValue[Day] = DAY_DEFAULT; - parseTimeZone(); - - validateDateTime(); - normalize(); -} - -// -//PnYn MnDTnH nMnS: -P1Y2M3DT10H30M -// -// [-]{'P'{[n'Y'][n'M'][n'D']['T'][n'H'][n'M'][n'S']}} -// -// Note: the n above shall be >= 0 -// if no time element found, 'T' shall be absent -// -void DateTime::parseDuration() -{ - initParser(); - - // must start with '-' or 'P' - // - XMLCh c = fBuffer[fStart++]; - if ( (c != DURATION_STARTER) && - (c != chDash) ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_dur_Start_dashP - , fBuffer); - } - - // 'P' must ALWAYS be present in either case - if ( (c == chDash) && - (fBuffer[fStart++]!= DURATION_STARTER )) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_dur_noP - , fBuffer); - } - - // java code - //date[utc]=(c=='-')?'-':0; - //fValue[utc] = UTC_STD; - fValue[utc] = (fBuffer[0] == chDash? UTC_NEG : UTC_STD); - - int negate = ( fBuffer[0] == chDash ? -1 : 1); - - // - // No negative value is allowed after 'P' - // - // eg P-1234, invalid - // - if (indexOf(fStart, fEnd, chDash) != NOT_FOUND) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_dur_DashNotFirst - , fBuffer); - } - - //at least one number and designator must be seen after P - bool designator = false; - - int endDate = indexOf(fStart, fEnd, DATETIME_SEPARATOR); - if ( endDate == NOT_FOUND ) - { - endDate = fEnd; // 'T' absent - } - - //find 'Y' - int end = indexOf(fStart, endDate, DURATION_Y); - if ( end != NOT_FOUND ) - { - //scan year - fValue[CentYear] = negate * parseInt(fStart, end); - fStart = end+1; - designator = true; - } - - end = indexOf(fStart, endDate, DURATION_M); - if ( end != NOT_FOUND ) - { - //scan month - fValue[Month] = negate * parseInt(fStart, end); - fStart = end+1; - designator = true; - } - - end = indexOf(fStart, endDate, DURATION_D); - if ( end != NOT_FOUND ) - { - //scan day - fValue[Day] = negate * parseInt(fStart,end); - fStart = end+1; - designator = true; - } - - if ( (fEnd == endDate) && // 'T' absent - (fStart != fEnd) ) // something after Day - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_dur_inv_b4T - , fBuffer); - } - - if ( fEnd != endDate ) // 'T' present - { - //scan hours, minutes, seconds - // - - // skip 'T' first - end = indexOf(++fStart, fEnd, DURATION_H); - if ( end != NOT_FOUND ) - { - //scan hours - fValue[Hour] = negate * parseInt(fStart, end); - fStart = end+1; - designator = true; - } - - end = indexOf(fStart, fEnd, DURATION_M); - if ( end != NOT_FOUND ) - { - //scan min - fValue[Minute] = negate * parseInt(fStart, end); - fStart = end+1; - designator = true; - } - - end = indexOf(fStart, fEnd, DURATION_S); - if ( end != NOT_FOUND ) - { - //scan seconds - int mlsec = indexOf (fStart, end, MILISECOND_SEPARATOR); - - /*** - * Schema Errata: E2-23 - * at least one digit must follow the decimal point if it appears. - * That is, the value of the seconds component must conform - * to the following pattern: [0-9]+(.[0-9]+)? - */ - if ( mlsec != NOT_FOUND ) - { - /*** - * make usure there is something after the '.' and before the end. - */ - if ( mlsec+1 == end ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_dur_inv_seconds - , fBuffer); - } - - fValue[Second] = negate * parseInt(fStart, mlsec); - fMiliSecond = negate * parseMiliSecond(mlsec+1, end); - } - else - { - fValue[Second] = negate * parseInt(fStart,end); - } - - fStart = end+1; - designator = true; - } - - // no additional data should appear after last item - // P1Y1M1DT is illigal value as well - if ( (fStart != fEnd) || - fBuffer[--fStart] == DATETIME_SEPARATOR ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_dur_NoTimeAfterT - , fBuffer); - } - } - - if ( !designator ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_dur_NoElementAtAll - , fBuffer); - } - -} - -// --------------------------------------------------------------------------- -// Scanners -// --------------------------------------------------------------------------- - -// -// [-]{CCYY-MM-DD} -// -// Note: CCYY could be more than 4 digits -// Assuming fStart point to the beginning of the Date Section -// fStart updated to point to the position right AFTER the second 'D' -// Since the lenght of CCYY might be variable, we can't check format upfront -// -void DateTime::getDate() -{ - - // Ensure enough chars in buffer - if ( (fStart+YMD_MIN_SIZE) > fEnd) - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_date_incomplete - , fBuffer); - - getYearMonth(); // Scan YearMonth and - // fStart point to the next '-' - - if (fBuffer[fStart++] != DATE_SEPARATOR) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_date_invalid - , fBuffer); - //("CCYY-MM must be followed by '-' sign"); - } - - fValue[Day] = parseInt(fStart, fStart+2); - fStart += 2 ; //fStart points right after the Day - - return; -} - -// -// hh:mm:ss[.msssss]['Z'] -// hh:mm:ss[.msssss][['+'|'-']hh:mm] -// 012345678 -// -// Note: Assuming fStart point to the beginning of the Time Section -// fStart updated to point to the position right AFTER the second 's' -// or ms if any -// -void DateTime::getTime() -{ - - // Ensure enough chars in buffer - if ( (fStart+TIME_MIN_SIZE) > fEnd) - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_time_incomplete - , fBuffer); - //"Imcomplete Time Format" - - // check (fixed) format first - if ((fBuffer[fStart + 2] != TIME_SEPARATOR) || - (fBuffer[fStart + 5] != TIME_SEPARATOR) ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_time_invalid - , fBuffer); - //("Error in parsing time" ); - } - - // - // get hours, minute and second - // - fValue[Hour] = parseInt(fStart + 0, fStart + 2); - fValue[Minute] = parseInt(fStart + 3, fStart + 5); - fValue[Second] = parseInt(fStart + 6, fStart + 8); - fStart += 8; - - // to see if any ms and/or utc part after that - if (fStart >= fEnd) - return; - - //find UTC sign if any - int sign = findUTCSign(fStart); - - //parse miliseconds - int milisec = (fBuffer[fStart] == MILISECOND_SEPARATOR)? fStart : NOT_FOUND; - if ( milisec != NOT_FOUND ) - { - fStart++; // skip the '.' - // make sure we have some thing between the '.' and fEnd - if (fStart >= fEnd) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_ms_noDigit - , fBuffer); - //("ms shall be present once '.' is present" ); - } - - if ( sign == NOT_FOUND ) - { - fMiliSecond = parseMiliSecond(fStart, fEnd); //get ms between '.' and fEnd - fStart = fEnd; - } - else - { - fMiliSecond = parseMiliSecond(fStart, sign); //get ms between UTC sign and fEnd - } - } - else if(sign == 0 || sign != fStart) - { - // seconds has more than 2 digits - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_min_invalid - , fBuffer); - } - - //parse UTC time zone (hh:mm) - if ( sign > 0 ) { - getTimeZone(sign); - } - -} - -// -// [-]{CCYY-MM} -// -// Note: CCYY could be more than 4 digits -// fStart updated to point AFTER the second 'M' (probably meet the fEnd) -// -void DateTime::getYearMonth() -{ - - // Ensure enough chars in buffer - if ( (fStart+YMONTH_MIN_SIZE) > fEnd) - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_ym_incomplete - , fBuffer); - //"Imcomplete YearMonth Format"; - - // skip the first leading '-' - int start = ( fBuffer[0] == chDash ) ? fStart + 1 : fStart; - - // - // search for year separator '-' - // - int yearSeparator = indexOf(start, fEnd, DATE_SEPARATOR); - if ( yearSeparator == NOT_FOUND) - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_ym_invalid - , fBuffer); - //("Year separator is missing or misplaced"); - - fValue[CentYear] = parseIntYear(yearSeparator); - fStart = yearSeparator + 1; //skip the '-' and point to the first M - - // - //gonna check we have enough byte for month - // - if ((fStart + 2) > fEnd ) - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_ym_noMonth - , fBuffer); - //"no month in buffer" - - fValue[Month] = parseInt(fStart, yearSeparator + 3); - fStart += 2; //fStart points right after the MONTH - - return; -} - -void DateTime::parseTimeZone() -{ - if ( fStart < fEnd ) - { - int sign = findUTCSign(fStart); - if ( sign < 0 ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_tz_noUTCsign - , fBuffer); - //("Error in month parsing"); - } - else - { - getTimeZone(sign); - } - } - - return; -} - -// -// 'Z' -// ['+'|'-']hh:mm -// -// Note: Assuming fStart points to the beginning of TimeZone section -// fStart updated to meet fEnd -// -void DateTime::getTimeZone(const int sign) -{ - - if ( fBuffer[sign] == UTC_STD_CHAR ) - { - if ((sign + 1) != fEnd ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_tz_stuffAfterZ - , fBuffer); - //"Error in parsing time zone"); - } - - return; - } - - // - // otherwise, it has to be this format - // '[+|-]'hh:mm - // 1 23456 7 - // sign fEnd - // - if ( ( ( sign + TIMEZONE_SIZE + 1) != fEnd ) || - ( fBuffer[sign + 3] != TIMEZONE_SEPARATOR ) ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_tz_invalid - , fBuffer); - //("Error in parsing time zone"); - } - - fTimeZone[hh] = parseInt(sign+1, sign+3); - fTimeZone[mm] = parseInt(sign+4, fEnd); - - return; -} - -// --------------------------------------------------------------------------- -// Validator and normalizer -// --------------------------------------------------------------------------- - -/** - * If timezone present - normalize dateTime [E Adding durations to dateTimes] - * - * @param date CCYY-MM-DDThh:mm:ss+03 - * @return CCYY-MM-DDThh:mm:ssZ - */ -void DateTime::normalize() -{ - - if ((fValue[utc] == UTC_UNKNOWN) || - (fValue[utc] == UTC_STD) ) - return; - - int negate = (fValue[utc] == UTC_POS)? -1: 1; - - // add mins - int temp = fValue[Minute] + negate * fTimeZone[mm]; - int carry = fQuotient(temp, 60); - fValue[Minute] = mod(temp, 60, carry); - - //add hours - temp = fValue[Hour] + negate * fTimeZone[hh] + carry; - carry = fQuotient(temp, 24); - fValue[Hour] = mod(temp, 24, carry); - - fValue[Day] += carry; - - while (1) - { - temp = maxDayInMonthFor(fValue[CentYear], fValue[Month]); - if (fValue[Day] < 1) - { - fValue[Day] += maxDayInMonthFor(fValue[CentYear], fValue[Month] - 1); - carry = -1; - } - else if ( fValue[Day] > temp ) - { - fValue[Day] -= temp; - carry = 1; - } - else - { - break; - } - - temp = fValue[Month] + carry; - fValue[Month] = modulo(temp, 1, 13); - fValue[CentYear] += fQuotient(temp, 1, 13); - } - - // set to normalized - fValue[utc] = UTC_STD; - - return; -} - -void DateTime::validateDateTime() const -{ - - //REVISIT: should we throw an exception for not valid dates - // or reporting an error message should be sufficient? - if ( fValue[CentYear] == 0 ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_year_zero - , fBuffer); - //"The year \"0000\" is an illegal year value"); - } - - if ( fValue[Month] < 1 || - fValue[Month] > 12 ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_mth_invalid - , fBuffer); - //"The month must have values 1 to 12"); - } - - //validate days - if ( fValue[Day] > maxDayInMonthFor( fValue[CentYear], fValue[Month]) || - fValue[Day] == 0 ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_day_invalid - , fBuffer); - //"The day must have values 1 to 31"); - } - - //validate hours - if ((fValue[Hour] < 0) || - (fValue[Hour] > 24) || - ((fValue[Hour] == 24) && ((fValue[Minute] !=0) || - (fValue[Second] !=0) || - (fMiliSecond !=0)))) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_hour_invalid - , fBuffer); - //("Hour must have values 0-23"); - } - - //validate minutes - if ( fValue[Minute] < 0 || - fValue[Minute] > 59 ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_min_invalid - , fBuffer); - //"Minute must have values 0-59"); - } - - //validate seconds - if ( fValue[Second] < 0 || - fValue[Second] > 60 ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_second_invalid - , fBuffer); - //"Second must have values 0-60"); - } - - //validate time-zone hours - if ( (abs(fTimeZone[hh]) > 14) || - ((abs(fTimeZone[hh]) == 14) && (fTimeZone[mm] != 0)) ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_tz_hh_invalid - , fBuffer); - //"Time zone should have range -14..+14"); - } - - //validate time-zone minutes - if ( abs(fTimeZone[mm]) > 59 ) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_min_invalid - , fBuffer); - //("Minute must have values 0-59"); - } - - return; -} - -// ----------------------------------------------------------------------- -// locator and converter -// ----------------------------------------------------------------------- -int DateTime::indexOf(const int start, const int end, const XMLCh ch) const -{ - for ( int i = start; i < end; i++ ) - if ( fBuffer[i] == ch ) - return i; - - return NOT_FOUND; -} - -int DateTime::findUTCSign (const int start) -{ - int pos; - for ( int index = start; index < fEnd; index++ ) - { - pos = XMLString::indexOf(UTC_SET, fBuffer[index]); - if ( pos != NOT_FOUND) - { - fValue[utc] = pos+1; // refer to utcType, there is 1 diff - return index; - } - } - - return NOT_FOUND; -} - -// -// Note: -// start: starting point in fBuffer -// end: ending point in fBuffer (exclusive) -// fStart NOT updated -// -int DateTime::parseInt(const int start, const int end) const -{ - unsigned int retVal = 0; - for (int i=start; i < end; i++) { - - if (fBuffer[i] < chDigit_0 || fBuffer[i] > chDigit_9) - ThrowXML(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars); - - retVal = (retVal * 10) + (unsigned int) (fBuffer[i] - chDigit_0); - } - - return (int) retVal; -} - -// -// Note: -// start: pointing to the first digit after the '.' -// end: pointing to one position after the last digit -// fStart NOT updated -// -double DateTime::parseMiliSecond(const int start, const int end) const -{ - - unsigned int miliSecLen = (end-1) - (start-1) + 1; //to include the '.' - XMLCh* miliSecData = new XMLCh[miliSecLen + 1]; - ArrayJanitor janMili(miliSecData); - XMLString::copyNString(miliSecData, &(fBuffer[start-1]), miliSecLen); - *(miliSecData + miliSecLen) = chNull; - - char *nptr = XMLString::transcode(miliSecData); - ArrayJanitor jan(nptr); - size_t strLen = strlen(nptr); - char *endptr = 0; - errno = 0; - - //printf("milisec=<%s>\n", nptr); - - double retVal = strtod(nptr, &endptr); - - // check if all chars are valid char - if ( (endptr - nptr) != strLen) - ThrowXML(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars); - - // we don't check underflow occurs since - // nothing we can do about it. - return retVal; -} - -// -// [-]CCYY -// -// Note: start from fStart -// end (exclusive) -// fStart NOT updated -// -int DateTime::parseIntYear(const int end) const -{ - // skip the first leading '-' - int start = ( fBuffer[0] == chDash ) ? fStart + 1 : fStart; - - int length = end - start; - if (length < 4) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_year_tooShort - , fBuffer); - //"Year must have 'CCYY' format"); - } - else if (length > 4 && - fBuffer[start] == chDigit_0) - { - ThrowXML1(SchemaDateTimeException - , XMLExcepts::DateTime_year_leadingZero - , fBuffer); - //"Leading zeros are required if the year value would otherwise have fewer than four digits; - // otherwise they are forbidden"); - } - - bool negative = (fBuffer[0] == chDash); - int yearVal = parseInt((negative ? 1 : 0), end); - return ( negative ? (-1) * yearVal : yearVal ); -} - -/*** - * E2-41 - * - * 3.2.7.2 Canonical representation - * - * Except for trailing fractional zero digits in the seconds representation, - * '24:00:00' time representations, and timezone (for timezoned values), - * the mapping from literals to values is one-to-one. Where there is more - * than one possible representation, the canonical representation is as follows: - * redundant trailing zero digits in fractional-second literals are prohibited. - * An hour representation of '24' is prohibited. Timezoned values are canonically - * represented by appending 'Z' to the nontimezoned representation. (All - * timezoned dateTime values are UTC.) - * - * .'24:00:00' -> '00:00:00' - * .milisecond: trailing zeros removed - * .'Z' - * - ***/ -XMLCh* DateTime::getDateTimeCanonicalRepresentation() const -{ - XMLCh *miliStartPtr, *miliEndPtr; - searchMiliSeconds(miliStartPtr, miliEndPtr); - size_t miliSecondsLen = miliEndPtr - miliStartPtr; - - XMLCh* retBuf = new XMLCh[21 + miliSecondsLen + 2]; - XMLCh* retPtr = retBuf; - - // (-?) cc+yy-mm-dd'T'hh:mm:ss'Z' ('.'s+)? - // 2+ 8 1 8 1 - // - int additionalLen = fillYearString(retPtr, CentYear); - if(additionalLen != 0) - { - // very bad luck; have to resize the buffer... - XMLCh *tmpBuf = new XMLCh[additionalLen+21+miliSecondsLen +2]; - XMLString::moveChars(tmpBuf, retBuf, 4+additionalLen); - retPtr = tmpBuf+(retPtr-retBuf); - delete[] retBuf; - retBuf = tmpBuf; - } - *retPtr++ = DATE_SEPARATOR; - fillString(retPtr, Month, 2); - *retPtr++ = DATE_SEPARATOR; - fillString(retPtr, Day, 2); - *retPtr++ = DATETIME_SEPARATOR; - - fillString(retPtr, Hour, 2); - if (fValue[Hour] == 24) - { - *(retPtr - 2) = chDigit_0; - *(retPtr - 1) = chDigit_0; - } - *retPtr++ = TIME_SEPARATOR; - fillString(retPtr, Minute, 2); - *retPtr++ = TIME_SEPARATOR; - fillString(retPtr, Second, 2); - - if (miliSecondsLen) - { - *retPtr++ = chPeriod; - XMLString::copyNString(retPtr, miliStartPtr, miliSecondsLen); - retPtr += miliSecondsLen; - } - - *retPtr++ = UTC_STD_CHAR; - *retPtr = chNull; - - return retBuf; -} - -/*** - * 3.2.8 time - * - * . either the time zone must be omitted or, - * if present, the time zone must be Coordinated Universal Time (UTC) indicated by a "Z". - * - * . Additionally, the canonical representation for midnight is 00:00:00. - * -***/ -XMLCh* DateTime::getTimeCanonicalRepresentation() const -{ - XMLCh *miliStartPtr, *miliEndPtr; - searchMiliSeconds(miliStartPtr, miliEndPtr); - size_t miliSecondsLen = miliEndPtr - miliStartPtr; - - XMLCh* retBuf = new XMLCh[10 + miliSecondsLen + 2]; - XMLCh* retPtr = retBuf; - - // 'hh:mm:ss'Z' ('.'s+)? - // 8 1 - // - - fillString(retPtr, Hour, 2); - if (fValue[Hour] == 24) - { - *(retPtr - 2) = chDigit_0; - *(retPtr - 1) = chDigit_0; - } - *retPtr++ = TIME_SEPARATOR; - fillString(retPtr, Minute, 2); - *retPtr++ = TIME_SEPARATOR; - fillString(retPtr, Second, 2); - - if (miliSecondsLen) - { - *retPtr++ = chPeriod; - XMLString::copyNString(retPtr, miliStartPtr, miliSecondsLen); - retPtr += miliSecondsLen; - } - - *retPtr++ = UTC_STD_CHAR; - *retPtr = chNull; - - return retBuf; -} - -void DateTime::fillString(XMLCh*& ptr, valueIndex ind, int expLen) const -{ - XMLCh strBuffer[16]; - assert(expLen < 16); - XMLString::binToText(fValue[ind], strBuffer, expLen, 10); - int actualLen = XMLString::stringLen(strBuffer); - int i; - //append leading zeros - for (i = 0; i < expLen - actualLen; i++) - { - *ptr++ = chDigit_0; - } - - for (i = 0; i < actualLen; i++) - { - *ptr++ = strBuffer[i]; - } - -} - -int DateTime::fillYearString(XMLCh*& ptr, valueIndex ind) const -{ - XMLCh strBuffer[16]; - // let's hope we get no years of 15 digits... - XMLString::binToText(fValue[ind], strBuffer, 15, 10); - int actualLen = XMLString::stringLen(strBuffer); - // don't forget that years can be negative... - int negativeYear = 0; - if(strBuffer[0] == chDash) - { - *ptr++ = strBuffer[0]; - negativeYear = 1; - } - int i; - //append leading zeros - for (i = 0; i < 4 - actualLen+negativeYear; i++) - { - *ptr++ = chDigit_0; - } - - for (i = negativeYear; i < actualLen; i++) - { - *ptr++ = strBuffer[i]; - } - if(actualLen > 4) - return actualLen-4; - return 0; -} - -/*** - * - * .check if the rawData has the mili second component - * .capture the substring - * - ***/ -void DateTime::searchMiliSeconds(XMLCh*& miliStartPtr, XMLCh*& miliEndPtr) const -{ - miliStartPtr = miliEndPtr = 0; - - int milisec = XMLString::indexOf(fBuffer, MILISECOND_SEPARATOR); - if (milisec == -1) - return; - - miliStartPtr = fBuffer + milisec + 1; - miliEndPtr = miliStartPtr; - while (*miliEndPtr) - { - if ((*miliEndPtr < chDigit_0) || (*miliEndPtr > chDigit_9)) - break; - - miliEndPtr++; - } - - //remove trailing zeros - while( *(miliEndPtr - 1) == chDigit_0) - miliEndPtr--; - - return; -} - +/* + * 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. + */ + +/** + * DateTime.cpp + * + * Manipulation of XML date/time data. + */ + +/* + * This is mostly copied from Xerces-C, but they don't seem inclined to produce a usable + * class, so I had to incorporate my own version of it for now. I can't inherit it + * since the fields I need are private. + */ + +#include "internal.h" +#include "util/DateTime.h" + +#ifndef WIN32 +# include +#endif + +#include +#include +#include + +using namespace xmltooling; +using namespace std; + +// +// constants used to process raw data (fBuffer) +// +// [-]{CCYY-MM-DD}'T'{HH:MM:SS.MS}['Z'] +// [{+|-}hh:mm'] +// + +static const XMLCh DURATION_STARTER = chLatin_P; // 'P' +static const XMLCh DURATION_Y = chLatin_Y; // 'Y' +static const XMLCh DURATION_M = chLatin_M; // 'M' +static const XMLCh DURATION_D = chLatin_D; // 'D' +static const XMLCh DURATION_H = chLatin_H; // 'H' +static const XMLCh DURATION_S = chLatin_S; // 'S' + +static const XMLCh DATE_SEPARATOR = chDash; // '-' +static const XMLCh TIME_SEPARATOR = chColon; // ':' +static const XMLCh TIMEZONE_SEPARATOR = chColon; // ':' +static const XMLCh DATETIME_SEPARATOR = chLatin_T; // 'T' +static const XMLCh MILISECOND_SEPARATOR = chPeriod; // '.' + +static const XMLCh UTC_STD_CHAR = chLatin_Z; // 'Z' +static const XMLCh UTC_POS_CHAR = chPlus; // '+' +static const XMLCh UTC_NEG_CHAR = chDash; // '-' + +static const XMLCh UTC_SET[] = {UTC_STD_CHAR //"Z+-" + , UTC_POS_CHAR + , UTC_NEG_CHAR + , chNull}; + +static const int YMD_MIN_SIZE = 10; // CCYY-MM-DD +static const int YMONTH_MIN_SIZE = 7; // CCYY_MM +static const int TIME_MIN_SIZE = 8; // hh:mm:ss +static const int TIMEZONE_SIZE = 5; // hh:mm +static const int DAY_SIZE = 5; // ---DD +//static const int MONTH_SIZE = 6; // --MM-- +static const int MONTHDAY_SIZE = 7; // --MM-DD +static const int NOT_FOUND = -1; + +//define constants to be used in assigning default values for +//all date/time excluding duration +static const int YEAR_DEFAULT = 2000; +static const int MONTH_DEFAULT = 01; +static const int DAY_DEFAULT = 15; + +// order-relation on duration is a partial order. The dates below are used to +// for comparison of 2 durations, based on the fact that +// duration x and y is x<=y iff s+x<=s+y +// see 3.2.6 duration W3C schema datatype specs +// +// the dates are in format: {CCYY,MM,DD, H, S, M, MS, timezone} +const int DateTime::DATETIMES[][TOTAL_SIZE] = +{ + {1696, 9, 1, 0, 0, 0, 0, UTC_STD}, + {1697, 2, 1, 0, 0, 0, 0, UTC_STD}, + {1903, 3, 1, 0, 0, 0, 0, UTC_STD}, + {1903, 7, 1, 0, 0, 0, 0, UTC_STD} +}; + +// --------------------------------------------------------------------------- +// local methods +// --------------------------------------------------------------------------- +static inline int fQuotient(int a, int b) +{ + div_t div_result = div(a, b); + return div_result.quot; +} + +static inline int fQuotient(int temp, int low, int high) +{ + return fQuotient(temp - low, high - low); +} + +static inline int mod(int a, int b, int quotient) +{ + return (a - quotient*b) ; +} + +static inline int modulo (int temp, int low, int high) +{ + //modulo(a - low, high - low) + low + int a = temp - low; + int b = high - low; + return (mod (a, b, fQuotient(a, b)) + low) ; +} + +static inline bool isLeapYear(int year) +{ + return((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))); +} + +static int maxDayInMonthFor(int year, int month) +{ + + if ( month == 4 || month == 6 || month == 9 || month == 11 ) + { + return 30; + } + else if ( month==2 ) + { + if ( isLeapYear(year) ) + return 29; + else + return 28; + } + else + { + return 31; + } + +} + +// --------------------------------------------------------------------------- +// static methods : for duration +// --------------------------------------------------------------------------- +/** + * Compares 2 given durations. (refer to W3C Schema Datatypes "3.2.6 duration") + * + * 3.2.6.2 Order relation on duration + * + * In general, the order-relation on duration is a partial order since there is no + * determinate relationship between certain durations such as one month (P1M) and 30 days (P30D). + * The order-relation of two duration values x and y is x < y iff s+x < s+y for each qualified + * dateTime s in the list below. + * + * These values for s cause the greatest deviations in the addition of dateTimes and durations + * + **/ +int DateTime::compare(const DateTime* const pDate1 + , const DateTime* const pDate2 + , bool strict) +{ + //REVISIT: this is unoptimazed vs of comparing 2 durations + // Algorithm is described in 3.2.6.2 W3C Schema Datatype specs + // + + int resultA, resultB = XMLDateTime::INDETERMINATE; + + //try and see if the objects are equal + if ( (resultA = compareOrder(pDate1, pDate2)) == XMLDateTime::EQUAL) + return XMLDateTime::EQUAL; + + //long comparison algorithm is required + DateTime tempA, *pTempA = &tempA; + DateTime tempB, *pTempB = &tempB; + + addDuration(pTempA, pDate1, 0); + addDuration(pTempB, pDate2, 0); + resultA = compareOrder(pTempA, pTempB); + if ( resultA == XMLDateTime::INDETERMINATE ) + return XMLDateTime::INDETERMINATE; + + addDuration(pTempA, pDate1, 1); + addDuration(pTempB, pDate2, 1); + resultB = compareOrder(pTempA, pTempB); + resultA = compareResult(resultA, resultB, strict); + if ( resultA == XMLDateTime::INDETERMINATE ) + return XMLDateTime::INDETERMINATE; + + addDuration(pTempA, pDate1, 2); + addDuration(pTempB, pDate2, 2); + resultB = compareOrder(pTempA, pTempB); + resultA = compareResult(resultA, resultB, strict); + if ( resultA == XMLDateTime::INDETERMINATE ) + return XMLDateTime::INDETERMINATE; + + addDuration(pTempA, pDate1, 3); + addDuration(pTempB, pDate2, 3); + resultB = compareOrder(pTempA, pTempB); + resultA = compareResult(resultA, resultB, strict); + + return resultA; + +} + +// +// Form a new DateTime with duration and baseDate array +// Note: C++ Java +// fNewDate duration +// fDuration date +// + +void DateTime::addDuration(DateTime* fNewDate + , const DateTime* const fDuration + , int index) + +{ + + //REVISIT: some code could be shared between normalize() and this method, + // however is it worth moving it? The structures are different... + // + + fNewDate->reset(); + //add months (may be modified additionaly below) + int temp = DATETIMES[index][Month] + fDuration->fValue[Month]; + fNewDate->fValue[Month] = modulo(temp, 1, 13); + int carry = fQuotient(temp, 1, 13); + + //add years (may be modified additionaly below) + fNewDate->fValue[CentYear] = + DATETIMES[index][CentYear] + fDuration->fValue[CentYear] + carry; + + //add seconds + temp = DATETIMES[index][Second] + fDuration->fValue[Second]; + carry = fQuotient (temp, 60); + fNewDate->fValue[Second] = mod(temp, 60, carry); + + //add minutes + temp = DATETIMES[index][Minute] + fDuration->fValue[Minute] + carry; + carry = fQuotient(temp, 60); + fNewDate->fValue[Minute] = mod(temp, 60, carry); + + //add hours + temp = DATETIMES[index][Hour] + fDuration->fValue[Hour] + carry; + carry = fQuotient(temp, 24); + fNewDate->fValue[Hour] = mod(temp, 24, carry); + + fNewDate->fValue[Day] = + DATETIMES[index][Day] + fDuration->fValue[Day] + carry; + + while ( true ) + { + temp = maxDayInMonthFor(fNewDate->fValue[CentYear], fNewDate->fValue[Month]); + if ( fNewDate->fValue[Day] < 1 ) + { //original fNewDate was negative + fNewDate->fValue[Day] += + maxDayInMonthFor(fNewDate->fValue[CentYear], fNewDate->fValue[Month]-1); + carry = -1; + } + else if ( fNewDate->fValue[Day] > temp ) + { + fNewDate->fValue[Day] -= temp; + carry = 1; + } + else + { + break; + } + + temp = fNewDate->fValue[Month] + carry; + fNewDate->fValue[Month] = modulo(temp, 1, 13); + fNewDate->fValue[CentYear] += fQuotient(temp, 1, 13); + } + + //fNewDate->fValue[utc] = UTC_STD_CHAR; + fNewDate->fValue[utc] = UTC_STD; +} + +int DateTime::compareResult(int resultA + , int resultB + , bool strict) +{ + + if ( resultB == XMLDateTime::INDETERMINATE ) + { + return XMLDateTime::INDETERMINATE; + } + else if ( (resultA != resultB) && + strict ) + { + return XMLDateTime::INDETERMINATE; + } + else if ( (resultA != resultB) && + !strict ) + { + if ( (resultA != XMLDateTime::EQUAL) && + (resultB != XMLDateTime::EQUAL) ) + { + return XMLDateTime::INDETERMINATE; + } + else + { + return (resultA != XMLDateTime::EQUAL)? resultA : resultB; + } + } + + return resultA; + +} + +// --------------------------------------------------------------------------- +// static methods : for others +// --------------------------------------------------------------------------- +int DateTime::compare(const DateTime* const pDate1 + , const DateTime* const pDate2) +{ + + if (pDate1->fValue[utc] == pDate2->fValue[utc]) + { + return DateTime::compareOrder(pDate1, pDate2); + } + + int c1, c2; + + if ( pDate1->isNormalized()) + { + c1 = compareResult(pDate1, pDate2, false, UTC_POS); + c2 = compareResult(pDate1, pDate2, false, UTC_NEG); + return getRetVal(c1, c2); + } + else if ( pDate2->isNormalized()) + { + c1 = compareResult(pDate1, pDate2, true, UTC_POS); + c2 = compareResult(pDate1, pDate2, true, UTC_NEG); + return getRetVal(c1, c2); + } + + return XMLDateTime::INDETERMINATE; +} + +int DateTime::compareResult(const DateTime* const pDate1 + , const DateTime* const pDate2 + , bool set2Left + , int utc_type) +{ + DateTime tmpDate = (set2Left ? *pDate1 : *pDate2); + + tmpDate.fTimeZone[hh] = 14; + tmpDate.fTimeZone[mm] = 0; + tmpDate.fValue[utc] = utc_type; + tmpDate.normalize(); + + return (set2Left? DateTime::compareOrder(&tmpDate, pDate2) : + DateTime::compareOrder(pDate1, &tmpDate)); +} + +int DateTime::compareOrder(const DateTime* const lValue + , const DateTime* const rValue) + //, MemoryManager* const memMgr) +{ + // + // If any of the them is not normalized() yet, + // we need to do something here. + // + DateTime lTemp = *lValue; + DateTime rTemp = *rValue; + + lTemp.normalize(); + rTemp.normalize(); + + for ( int i = 0 ; i < TOTAL_SIZE; i++ ) + { + if ( lTemp.fValue[i] < rTemp.fValue[i] ) + { + return XMLDateTime::LESS_THAN; + } + else if ( lTemp.fValue[i] > rTemp.fValue[i] ) + { + return XMLDateTime::GREATER_THAN; + } + } + + if ( lTemp.fHasTime) + { + if ( lTemp.fMiliSecond < rTemp.fMiliSecond ) + { + return XMLDateTime::LESS_THAN; + } + else if ( lTemp.fMiliSecond > rTemp.fMiliSecond ) + { + return XMLDateTime::GREATER_THAN; + } + } + + return XMLDateTime::EQUAL; +} + +// --------------------------------------------------------------------------- +// ctor and dtor +// --------------------------------------------------------------------------- +DateTime::~DateTime() +{ + delete[] fBuffer; +} + +DateTime::DateTime() +: fStart(0) +, fEnd(0) +, fBufferMaxLen(0) +, fBuffer(0) +, fMiliSecond(0) +, fHasTime(false) +{ + reset(); +} + +DateTime::DateTime(const XMLCh* const aString) +: fStart(0) +, fEnd(0) +, fBufferMaxLen(0) +, fBuffer(0) +, fMiliSecond(0) +, fHasTime(false) +{ + setBuffer(aString); +} + +DateTime::DateTime(time_t epoch) +: fStart(0) +, fEnd(0) +, fBufferMaxLen(0) +, fBuffer(0) +, fMiliSecond(0) +, fHasTime(false) +{ +#ifndef HAVE_GMTIME_R + struct tm* ptime=gmtime(&epoch); +#else + struct tm res; + struct tm* ptime=gmtime_r(&epoch,&res); +#endif + char timebuf[32]; + strftime(timebuf,32,"%Y-%m-%dT%H:%M:%SZ",ptime); + auto_ptr_XMLCh timeptr(timebuf); + setBuffer(timeptr.get()); +} + +// ----------------------------------------------------------------------- +// Copy ctor and Assignment operators +// ----------------------------------------------------------------------- + +DateTime::DateTime(const DateTime &toCopy) +: fBufferMaxLen(0) +, fBuffer(0) +{ + copy(toCopy); +} + +DateTime& DateTime::operator=(const DateTime& rhs) +{ + if (this == &rhs) + return *this; + + copy(rhs); + return *this; +} + +// ----------------------------------------------------------------------- +// Implementation of Abstract Interface +// ----------------------------------------------------------------------- + +// +// We may simply return the handle to fBuffer +// +const XMLCh* DateTime::getRawData() const +{ + //assertBuffer(); + return fBuffer; +} + + +const XMLCh* DateTime::getFormattedString() const +{ + return getRawData(); +} + +int DateTime::getSign() const +{ + return 0; +} + +time_t DateTime::getEpoch() const +{ + struct tm t; + t.tm_sec=getSecond(); + t.tm_min=getMinute(); + t.tm_hour=getHour(); + t.tm_mday=getDay(); + t.tm_mon=getMonth()-1; + t.tm_year=getYear()-1900; + t.tm_isdst=0; +#if defined(HAVE_TIMEGM) + return timegm(&t); +#else + // Windows, and hopefully most others...? + return mktime(&t) - timezone; +#endif +} + +// --------------------------------------------------------------------------- +// Parsers +// --------------------------------------------------------------------------- + +// +// [-]{CCYY-MM-DD}'T'{HH:MM:SS.MS}[TimeZone] +// +void DateTime::parseDateTime() +{ + initParser(); + getDate(); + + //fStart is supposed to point to 'T' + if (fBuffer[fStart++] != DATETIME_SEPARATOR) + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_gDay_invalid + , fBuffer); + + getTime(); + validateDateTime(); + normalize(); + fHasTime = true; +} + +// +// [-]{CCYY-MM-DD}[TimeZone] +// +void DateTime::parseDate() +{ + initParser(); + getDate(); + parseTimeZone(); + validateDateTime(); + normalize(); +} + +void DateTime::parseTime() +{ + initParser(); + + // time initialize to default values + fValue[CentYear]= YEAR_DEFAULT; + fValue[Month] = MONTH_DEFAULT; + fValue[Day] = DAY_DEFAULT; + + getTime(); + + validateDateTime(); + normalize(); + fHasTime = true; +} + +// +// {---DD}[TimeZone] +// 01234 +// +void DateTime::parseDay() +{ + initParser(); + + if (fBuffer[0] != DATE_SEPARATOR || + fBuffer[1] != DATE_SEPARATOR || + fBuffer[2] != DATE_SEPARATOR ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_gDay_invalid + , fBuffer); + } + + //initialize values + fValue[CentYear] = YEAR_DEFAULT; + fValue[Month] = MONTH_DEFAULT; + fValue[Day] = parseInt(fStart+3, fStart+5); + + if ( DAY_SIZE < fEnd ) + { + int sign = findUTCSign(DAY_SIZE); + if ( sign < 0 ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_gDay_invalid + , fBuffer); + } + else + { + getTimeZone(sign); + } + } + + validateDateTime(); + normalize(); +} + +// +// {--MM--}[TimeZone] +// {--MM}[TimeZone] +// 012345 +// +void DateTime::parseMonth() +{ + initParser(); + + if (fBuffer[0] != DATE_SEPARATOR || + fBuffer[1] != DATE_SEPARATOR ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_gMth_invalid + , fBuffer); + } + + //set constants + fValue[CentYear] = YEAR_DEFAULT; + fValue[Day] = DAY_DEFAULT; + fValue[Month] = parseInt(2, 4); + + // REVISIT: allow both --MM and --MM-- now. + // need to remove the following lines to disallow --MM-- + // when the errata is officially in the rec. + fStart = 4; + if ( fEnd >= fStart+2 && fBuffer[fStart] == DATE_SEPARATOR && fBuffer[fStart+1] == DATE_SEPARATOR ) + { + fStart += 2; + } + + // + // parse TimeZone if any + // + if ( fStart < fEnd ) + { + int sign = findUTCSign(fStart); + if ( sign < 0 ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_gMth_invalid + , fBuffer); + } + else + { + getTimeZone(sign); + } + } + + validateDateTime(); + normalize(); +} + +// +//[-]{CCYY}[TimeZone] +// 0 1234 +// +void DateTime::parseYear() +{ + initParser(); + + // skip the first '-' and search for timezone + // + int sign = findUTCSign((fBuffer[0] == chDash) ? 1 : 0); + + if (sign == NOT_FOUND) + { + fValue[CentYear] = parseIntYear(fEnd); + } + else + { + fValue[CentYear] = parseIntYear(sign); + getTimeZone(sign); + } + + //initialize values + fValue[Month] = MONTH_DEFAULT; + fValue[Day] = DAY_DEFAULT; //java is 1 + + validateDateTime(); + normalize(); +} + +// +//{--MM-DD}[TimeZone] +// 0123456 +// +void DateTime::parseMonthDay() +{ + initParser(); + + if (fBuffer[0] != DATE_SEPARATOR || + fBuffer[1] != DATE_SEPARATOR || + fBuffer[4] != DATE_SEPARATOR ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_gMthDay_invalid + , fBuffer); + } + + + //initialize + fValue[CentYear] = YEAR_DEFAULT; + fValue[Month] = parseInt(2, 4); + fValue[Day] = parseInt(5, 7); + + if ( MONTHDAY_SIZE < fEnd ) + { + int sign = findUTCSign(MONTHDAY_SIZE); + if ( sign<0 ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_gMthDay_invalid + , fBuffer); + } + else + { + getTimeZone(sign); + } + } + + validateDateTime(); + normalize(); +} + +void DateTime::parseYearMonth() +{ + initParser(); + + // get date + getYearMonth(); + fValue[Day] = DAY_DEFAULT; + parseTimeZone(); + + validateDateTime(); + normalize(); +} + +// +//PnYn MnDTnH nMnS: -P1Y2M3DT10H30M +// +// [-]{'P'{[n'Y'][n'M'][n'D']['T'][n'H'][n'M'][n'S']}} +// +// Note: the n above shall be >= 0 +// if no time element found, 'T' shall be absent +// +void DateTime::parseDuration() +{ + initParser(); + + // must start with '-' or 'P' + // + XMLCh c = fBuffer[fStart++]; + if ( (c != DURATION_STARTER) && + (c != chDash) ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_dur_Start_dashP + , fBuffer); + } + + // 'P' must ALWAYS be present in either case + if ( (c == chDash) && + (fBuffer[fStart++]!= DURATION_STARTER )) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_dur_noP + , fBuffer); + } + + // java code + //date[utc]=(c=='-')?'-':0; + //fValue[utc] = UTC_STD; + fValue[utc] = (fBuffer[0] == chDash? UTC_NEG : UTC_STD); + + int negate = ( fBuffer[0] == chDash ? -1 : 1); + + // + // No negative value is allowed after 'P' + // + // eg P-1234, invalid + // + if (indexOf(fStart, fEnd, chDash) != NOT_FOUND) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_dur_DashNotFirst + , fBuffer); + } + + //at least one number and designator must be seen after P + bool designator = false; + + int endDate = indexOf(fStart, fEnd, DATETIME_SEPARATOR); + if ( endDate == NOT_FOUND ) + { + endDate = fEnd; // 'T' absent + } + + //find 'Y' + int end = indexOf(fStart, endDate, DURATION_Y); + if ( end != NOT_FOUND ) + { + //scan year + fValue[CentYear] = negate * parseInt(fStart, end); + fStart = end+1; + designator = true; + } + + end = indexOf(fStart, endDate, DURATION_M); + if ( end != NOT_FOUND ) + { + //scan month + fValue[Month] = negate * parseInt(fStart, end); + fStart = end+1; + designator = true; + } + + end = indexOf(fStart, endDate, DURATION_D); + if ( end != NOT_FOUND ) + { + //scan day + fValue[Day] = negate * parseInt(fStart,end); + fStart = end+1; + designator = true; + } + + if ( (fEnd == endDate) && // 'T' absent + (fStart != fEnd) ) // something after Day + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_dur_inv_b4T + , fBuffer); + } + + if ( fEnd != endDate ) // 'T' present + { + //scan hours, minutes, seconds + // + + // skip 'T' first + end = indexOf(++fStart, fEnd, DURATION_H); + if ( end != NOT_FOUND ) + { + //scan hours + fValue[Hour] = negate * parseInt(fStart, end); + fStart = end+1; + designator = true; + } + + end = indexOf(fStart, fEnd, DURATION_M); + if ( end != NOT_FOUND ) + { + //scan min + fValue[Minute] = negate * parseInt(fStart, end); + fStart = end+1; + designator = true; + } + + end = indexOf(fStart, fEnd, DURATION_S); + if ( end != NOT_FOUND ) + { + //scan seconds + int mlsec = indexOf (fStart, end, MILISECOND_SEPARATOR); + + /*** + * Schema Errata: E2-23 + * at least one digit must follow the decimal point if it appears. + * That is, the value of the seconds component must conform + * to the following pattern: [0-9]+(.[0-9]+)? + */ + if ( mlsec != NOT_FOUND ) + { + /*** + * make usure there is something after the '.' and before the end. + */ + if ( mlsec+1 == end ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_dur_inv_seconds + , fBuffer); + } + + fValue[Second] = negate * parseInt(fStart, mlsec); + fMiliSecond = negate * parseMiliSecond(mlsec+1, end); + } + else + { + fValue[Second] = negate * parseInt(fStart,end); + } + + fStart = end+1; + designator = true; + } + + // no additional data should appear after last item + // P1Y1M1DT is illigal value as well + if ( (fStart != fEnd) || + fBuffer[--fStart] == DATETIME_SEPARATOR ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_dur_NoTimeAfterT + , fBuffer); + } + } + + if ( !designator ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_dur_NoElementAtAll + , fBuffer); + } + +} + +// --------------------------------------------------------------------------- +// Scanners +// --------------------------------------------------------------------------- + +// +// [-]{CCYY-MM-DD} +// +// Note: CCYY could be more than 4 digits +// Assuming fStart point to the beginning of the Date Section +// fStart updated to point to the position right AFTER the second 'D' +// Since the lenght of CCYY might be variable, we can't check format upfront +// +void DateTime::getDate() +{ + + // Ensure enough chars in buffer + if ( (fStart+YMD_MIN_SIZE) > fEnd) + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_date_incomplete + , fBuffer); + + getYearMonth(); // Scan YearMonth and + // fStart point to the next '-' + + if (fBuffer[fStart++] != DATE_SEPARATOR) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_date_invalid + , fBuffer); + //("CCYY-MM must be followed by '-' sign"); + } + + fValue[Day] = parseInt(fStart, fStart+2); + fStart += 2 ; //fStart points right after the Day + + return; +} + +// +// hh:mm:ss[.msssss]['Z'] +// hh:mm:ss[.msssss][['+'|'-']hh:mm] +// 012345678 +// +// Note: Assuming fStart point to the beginning of the Time Section +// fStart updated to point to the position right AFTER the second 's' +// or ms if any +// +void DateTime::getTime() +{ + + // Ensure enough chars in buffer + if ( (fStart+TIME_MIN_SIZE) > fEnd) + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_time_incomplete + , fBuffer); + //"Imcomplete Time Format" + + // check (fixed) format first + if ((fBuffer[fStart + 2] != TIME_SEPARATOR) || + (fBuffer[fStart + 5] != TIME_SEPARATOR) ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_time_invalid + , fBuffer); + //("Error in parsing time" ); + } + + // + // get hours, minute and second + // + fValue[Hour] = parseInt(fStart + 0, fStart + 2); + fValue[Minute] = parseInt(fStart + 3, fStart + 5); + fValue[Second] = parseInt(fStart + 6, fStart + 8); + fStart += 8; + + // to see if any ms and/or utc part after that + if (fStart >= fEnd) + return; + + //find UTC sign if any + int sign = findUTCSign(fStart); + + //parse miliseconds + int milisec = (fBuffer[fStart] == MILISECOND_SEPARATOR)? fStart : NOT_FOUND; + if ( milisec != NOT_FOUND ) + { + fStart++; // skip the '.' + // make sure we have some thing between the '.' and fEnd + if (fStart >= fEnd) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_ms_noDigit + , fBuffer); + //("ms shall be present once '.' is present" ); + } + + if ( sign == NOT_FOUND ) + { + fMiliSecond = parseMiliSecond(fStart, fEnd); //get ms between '.' and fEnd + fStart = fEnd; + } + else + { + fMiliSecond = parseMiliSecond(fStart, sign); //get ms between UTC sign and fEnd + } + } + else if(sign == 0 || sign != fStart) + { + // seconds has more than 2 digits + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_min_invalid + , fBuffer); + } + + //parse UTC time zone (hh:mm) + if ( sign > 0 ) { + getTimeZone(sign); + } + +} + +// +// [-]{CCYY-MM} +// +// Note: CCYY could be more than 4 digits +// fStart updated to point AFTER the second 'M' (probably meet the fEnd) +// +void DateTime::getYearMonth() +{ + + // Ensure enough chars in buffer + if ( (fStart+YMONTH_MIN_SIZE) > fEnd) + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_ym_incomplete + , fBuffer); + //"Imcomplete YearMonth Format"; + + // skip the first leading '-' + int start = ( fBuffer[0] == chDash ) ? fStart + 1 : fStart; + + // + // search for year separator '-' + // + int yearSeparator = indexOf(start, fEnd, DATE_SEPARATOR); + if ( yearSeparator == NOT_FOUND) + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_ym_invalid + , fBuffer); + //("Year separator is missing or misplaced"); + + fValue[CentYear] = parseIntYear(yearSeparator); + fStart = yearSeparator + 1; //skip the '-' and point to the first M + + // + //gonna check we have enough byte for month + // + if ((fStart + 2) > fEnd ) + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_ym_noMonth + , fBuffer); + //"no month in buffer" + + fValue[Month] = parseInt(fStart, yearSeparator + 3); + fStart += 2; //fStart points right after the MONTH + + return; +} + +void DateTime::parseTimeZone() +{ + if ( fStart < fEnd ) + { + int sign = findUTCSign(fStart); + if ( sign < 0 ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_tz_noUTCsign + , fBuffer); + //("Error in month parsing"); + } + else + { + getTimeZone(sign); + } + } + + return; +} + +// +// 'Z' +// ['+'|'-']hh:mm +// +// Note: Assuming fStart points to the beginning of TimeZone section +// fStart updated to meet fEnd +// +void DateTime::getTimeZone(const int sign) +{ + + if ( fBuffer[sign] == UTC_STD_CHAR ) + { + if ((sign + 1) != fEnd ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_tz_stuffAfterZ + , fBuffer); + //"Error in parsing time zone"); + } + + return; + } + + // + // otherwise, it has to be this format + // '[+|-]'hh:mm + // 1 23456 7 + // sign fEnd + // + if ( ( ( sign + TIMEZONE_SIZE + 1) != fEnd ) || + ( fBuffer[sign + 3] != TIMEZONE_SEPARATOR ) ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_tz_invalid + , fBuffer); + //("Error in parsing time zone"); + } + + fTimeZone[hh] = parseInt(sign+1, sign+3); + fTimeZone[mm] = parseInt(sign+4, fEnd); + + return; +} + +// --------------------------------------------------------------------------- +// Validator and normalizer +// --------------------------------------------------------------------------- + +/** + * If timezone present - normalize dateTime [E Adding durations to dateTimes] + * + * @param date CCYY-MM-DDThh:mm:ss+03 + * @return CCYY-MM-DDThh:mm:ssZ + */ +void DateTime::normalize() +{ + + if ((fValue[utc] == UTC_UNKNOWN) || + (fValue[utc] == UTC_STD) ) + return; + + int negate = (fValue[utc] == UTC_POS)? -1: 1; + + // add mins + int temp = fValue[Minute] + negate * fTimeZone[mm]; + int carry = fQuotient(temp, 60); + fValue[Minute] = mod(temp, 60, carry); + + //add hours + temp = fValue[Hour] + negate * fTimeZone[hh] + carry; + carry = fQuotient(temp, 24); + fValue[Hour] = mod(temp, 24, carry); + + fValue[Day] += carry; + + while (1) + { + temp = maxDayInMonthFor(fValue[CentYear], fValue[Month]); + if (fValue[Day] < 1) + { + fValue[Day] += maxDayInMonthFor(fValue[CentYear], fValue[Month] - 1); + carry = -1; + } + else if ( fValue[Day] > temp ) + { + fValue[Day] -= temp; + carry = 1; + } + else + { + break; + } + + temp = fValue[Month] + carry; + fValue[Month] = modulo(temp, 1, 13); + fValue[CentYear] += fQuotient(temp, 1, 13); + } + + // set to normalized + fValue[utc] = UTC_STD; + + return; +} + +void DateTime::validateDateTime() const +{ + + //REVISIT: should we throw an exception for not valid dates + // or reporting an error message should be sufficient? + if ( fValue[CentYear] == 0 ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_year_zero + , fBuffer); + //"The year \"0000\" is an illegal year value"); + } + + if ( fValue[Month] < 1 || + fValue[Month] > 12 ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_mth_invalid + , fBuffer); + //"The month must have values 1 to 12"); + } + + //validate days + if ( fValue[Day] > maxDayInMonthFor( fValue[CentYear], fValue[Month]) || + fValue[Day] == 0 ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_day_invalid + , fBuffer); + //"The day must have values 1 to 31"); + } + + //validate hours + if ((fValue[Hour] < 0) || + (fValue[Hour] > 24) || + ((fValue[Hour] == 24) && ((fValue[Minute] !=0) || + (fValue[Second] !=0) || + (fMiliSecond !=0)))) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_hour_invalid + , fBuffer); + //("Hour must have values 0-23"); + } + + //validate minutes + if ( fValue[Minute] < 0 || + fValue[Minute] > 59 ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_min_invalid + , fBuffer); + //"Minute must have values 0-59"); + } + + //validate seconds + if ( fValue[Second] < 0 || + fValue[Second] > 60 ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_second_invalid + , fBuffer); + //"Second must have values 0-60"); + } + + //validate time-zone hours + if ( (abs(fTimeZone[hh]) > 14) || + ((abs(fTimeZone[hh]) == 14) && (fTimeZone[mm] != 0)) ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_tz_hh_invalid + , fBuffer); + //"Time zone should have range -14..+14"); + } + + //validate time-zone minutes + if ( abs(fTimeZone[mm]) > 59 ) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_min_invalid + , fBuffer); + //("Minute must have values 0-59"); + } + + return; +} + +// ----------------------------------------------------------------------- +// locator and converter +// ----------------------------------------------------------------------- +int DateTime::indexOf(const int start, const int end, const XMLCh ch) const +{ + for ( int i = start; i < end; i++ ) + if ( fBuffer[i] == ch ) + return i; + + return NOT_FOUND; +} + +int DateTime::findUTCSign (const int start) +{ + int pos; + for ( int index = start; index < fEnd; index++ ) + { + pos = XMLString::indexOf(UTC_SET, fBuffer[index]); + if ( pos != NOT_FOUND) + { + fValue[utc] = pos+1; // refer to utcType, there is 1 diff + return index; + } + } + + return NOT_FOUND; +} + +// +// Note: +// start: starting point in fBuffer +// end: ending point in fBuffer (exclusive) +// fStart NOT updated +// +int DateTime::parseInt(const int start, const int end) const +{ + unsigned int retVal = 0; + for (int i=start; i < end; i++) { + + if (fBuffer[i] < chDigit_0 || fBuffer[i] > chDigit_9) + ThrowXML(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars); + + retVal = (retVal * 10) + (unsigned int) (fBuffer[i] - chDigit_0); + } + + return (int) retVal; +} + +// +// Note: +// start: pointing to the first digit after the '.' +// end: pointing to one position after the last digit +// fStart NOT updated +// +double DateTime::parseMiliSecond(const int start, const int end) const +{ + + unsigned int miliSecLen = (end-1) - (start-1) + 1; //to include the '.' + XMLCh* miliSecData = new XMLCh[miliSecLen + 1]; + ArrayJanitor janMili(miliSecData); + XMLString::copyNString(miliSecData, &(fBuffer[start-1]), miliSecLen); + *(miliSecData + miliSecLen) = chNull; + + char *nptr = XMLString::transcode(miliSecData); + ArrayJanitor jan(nptr); + size_t strLen = strlen(nptr); + char *endptr = 0; + errno = 0; + + //printf("milisec=<%s>\n", nptr); + + double retVal = strtod(nptr, &endptr); + + // check if all chars are valid char + if ( (endptr - nptr) != strLen) + ThrowXML(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars); + + // we don't check underflow occurs since + // nothing we can do about it. + return retVal; +} + +// +// [-]CCYY +// +// Note: start from fStart +// end (exclusive) +// fStart NOT updated +// +int DateTime::parseIntYear(const int end) const +{ + // skip the first leading '-' + int start = ( fBuffer[0] == chDash ) ? fStart + 1 : fStart; + + int length = end - start; + if (length < 4) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_year_tooShort + , fBuffer); + //"Year must have 'CCYY' format"); + } + else if (length > 4 && + fBuffer[start] == chDigit_0) + { + ThrowXML1(SchemaDateTimeException + , XMLExcepts::DateTime_year_leadingZero + , fBuffer); + //"Leading zeros are required if the year value would otherwise have fewer than four digits; + // otherwise they are forbidden"); + } + + bool negative = (fBuffer[0] == chDash); + int yearVal = parseInt((negative ? 1 : 0), end); + return ( negative ? (-1) * yearVal : yearVal ); +} + +/*** + * E2-41 + * + * 3.2.7.2 Canonical representation + * + * Except for trailing fractional zero digits in the seconds representation, + * '24:00:00' time representations, and timezone (for timezoned values), + * the mapping from literals to values is one-to-one. Where there is more + * than one possible representation, the canonical representation is as follows: + * redundant trailing zero digits in fractional-second literals are prohibited. + * An hour representation of '24' is prohibited. Timezoned values are canonically + * represented by appending 'Z' to the nontimezoned representation. (All + * timezoned dateTime values are UTC.) + * + * .'24:00:00' -> '00:00:00' + * .milisecond: trailing zeros removed + * .'Z' + * + ***/ +XMLCh* DateTime::getDateTimeCanonicalRepresentation() const +{ + XMLCh *miliStartPtr, *miliEndPtr; + searchMiliSeconds(miliStartPtr, miliEndPtr); + size_t miliSecondsLen = miliEndPtr - miliStartPtr; + + XMLCh* retBuf = new XMLCh[21 + miliSecondsLen + 2]; + XMLCh* retPtr = retBuf; + + // (-?) cc+yy-mm-dd'T'hh:mm:ss'Z' ('.'s+)? + // 2+ 8 1 8 1 + // + int additionalLen = fillYearString(retPtr, CentYear); + if(additionalLen != 0) + { + // very bad luck; have to resize the buffer... + XMLCh *tmpBuf = new XMLCh[additionalLen+21+miliSecondsLen +2]; + XMLString::moveChars(tmpBuf, retBuf, 4+additionalLen); + retPtr = tmpBuf+(retPtr-retBuf); + delete[] retBuf; + retBuf = tmpBuf; + } + *retPtr++ = DATE_SEPARATOR; + fillString(retPtr, Month, 2); + *retPtr++ = DATE_SEPARATOR; + fillString(retPtr, Day, 2); + *retPtr++ = DATETIME_SEPARATOR; + + fillString(retPtr, Hour, 2); + if (fValue[Hour] == 24) + { + *(retPtr - 2) = chDigit_0; + *(retPtr - 1) = chDigit_0; + } + *retPtr++ = TIME_SEPARATOR; + fillString(retPtr, Minute, 2); + *retPtr++ = TIME_SEPARATOR; + fillString(retPtr, Second, 2); + + if (miliSecondsLen) + { + *retPtr++ = chPeriod; + XMLString::copyNString(retPtr, miliStartPtr, miliSecondsLen); + retPtr += miliSecondsLen; + } + + *retPtr++ = UTC_STD_CHAR; + *retPtr = chNull; + + return retBuf; +} + +/*** + * 3.2.8 time + * + * . either the time zone must be omitted or, + * if present, the time zone must be Coordinated Universal Time (UTC) indicated by a "Z". + * + * . Additionally, the canonical representation for midnight is 00:00:00. + * +***/ +XMLCh* DateTime::getTimeCanonicalRepresentation() const +{ + XMLCh *miliStartPtr, *miliEndPtr; + searchMiliSeconds(miliStartPtr, miliEndPtr); + size_t miliSecondsLen = miliEndPtr - miliStartPtr; + + XMLCh* retBuf = new XMLCh[10 + miliSecondsLen + 2]; + XMLCh* retPtr = retBuf; + + // 'hh:mm:ss'Z' ('.'s+)? + // 8 1 + // + + fillString(retPtr, Hour, 2); + if (fValue[Hour] == 24) + { + *(retPtr - 2) = chDigit_0; + *(retPtr - 1) = chDigit_0; + } + *retPtr++ = TIME_SEPARATOR; + fillString(retPtr, Minute, 2); + *retPtr++ = TIME_SEPARATOR; + fillString(retPtr, Second, 2); + + if (miliSecondsLen) + { + *retPtr++ = chPeriod; + XMLString::copyNString(retPtr, miliStartPtr, miliSecondsLen); + retPtr += miliSecondsLen; + } + + *retPtr++ = UTC_STD_CHAR; + *retPtr = chNull; + + return retBuf; +} + +void DateTime::fillString(XMLCh*& ptr, valueIndex ind, int expLen) const +{ + XMLCh strBuffer[16]; + assert(expLen < 16); + XMLString::binToText(fValue[ind], strBuffer, expLen, 10); + int actualLen = XMLString::stringLen(strBuffer); + int i; + //append leading zeros + for (i = 0; i < expLen - actualLen; i++) + { + *ptr++ = chDigit_0; + } + + for (i = 0; i < actualLen; i++) + { + *ptr++ = strBuffer[i]; + } + +} + +int DateTime::fillYearString(XMLCh*& ptr, valueIndex ind) const +{ + XMLCh strBuffer[16]; + // let's hope we get no years of 15 digits... + XMLString::binToText(fValue[ind], strBuffer, 15, 10); + int actualLen = XMLString::stringLen(strBuffer); + // don't forget that years can be negative... + int negativeYear = 0; + if(strBuffer[0] == chDash) + { + *ptr++ = strBuffer[0]; + negativeYear = 1; + } + int i; + //append leading zeros + for (i = 0; i < 4 - actualLen+negativeYear; i++) + { + *ptr++ = chDigit_0; + } + + for (i = negativeYear; i < actualLen; i++) + { + *ptr++ = strBuffer[i]; + } + if(actualLen > 4) + return actualLen-4; + return 0; +} + +/*** + * + * .check if the rawData has the mili second component + * .capture the substring + * + ***/ +void DateTime::searchMiliSeconds(XMLCh*& miliStartPtr, XMLCh*& miliEndPtr) const +{ + miliStartPtr = miliEndPtr = 0; + + int milisec = XMLString::indexOf(fBuffer, MILISECOND_SEPARATOR); + if (milisec == -1) + return; + + miliStartPtr = fBuffer + milisec + 1; + miliEndPtr = miliStartPtr; + while (*miliEndPtr) + { + if ((*miliEndPtr < chDigit_0) || (*miliEndPtr > chDigit_9)) + break; + + miliEndPtr++; + } + + //remove trailing zeros + while( *(miliEndPtr - 1) == chDigit_0) + miliEndPtr--; + + return; +} + diff --git a/xmltooling/util/DateTime.h b/xmltooling/util/DateTime.h index aceaf22..44ce374 100644 --- a/xmltooling/util/DateTime.h +++ b/xmltooling/util/DateTime.h @@ -1,233 +1,233 @@ -/* - * 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 DateTime.h - * - * Manipulation of XML date/time data. - */ - -#ifndef _XML_DATETIME_H -#define _XML_DATETIME_H - -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4244 ) -#endif - -#include - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -namespace xmltooling -{ - /** - * Class for manipulating XML date/time information. - * - * This is mostly copied from Xerces-C, but they haven't produced a usable date/time - * class, so we had to incorporate a version of it for now. It can't be inherited - * since the fields needed are private. - */ - class XMLTOOL_API DateTime - { - public: - /// @cond OFF - DateTime(); - DateTime(const XMLCh* const); - DateTime(time_t epoch); - DateTime(const DateTime&); - DateTime& operator=(const DateTime&); - ~DateTime(); - - inline void setBuffer(const XMLCh* const); - - const XMLCh* getRawData() const; - const XMLCh* getFormattedString() const; - int getSign() const; - - XMLCh* getDateTimeCanonicalRepresentation() const; - XMLCh* getTimeCanonicalRepresentation() const; - - void parseDateTime(); - void parseDate(); - void parseTime(); - void parseDay(); - void parseMonth(); - void parseYear(); - void parseMonthDay(); - void parseYearMonth(); - void parseDuration(); - - static int compare(const DateTime* const, const DateTime* const); - static int compare(const DateTime* const, const DateTime* const, bool); - static int compareOrder(const DateTime* const, const DateTime* const); - - int getYear() const {return fValue[CentYear];} - int getMonth() const {return fValue[Month];} - int getDay() const {return fValue[Day];} - int getHour() const {return fValue[Hour];} - int getMinute() const {return fValue[Minute];} - int getSecond() const {return fValue[Second];} - time_t getEpoch() const; - - /// @endcond - private: - enum valueIndex { - CentYear = 0, - Month , - Day , - Hour , - Minute , - Second , - MiliSecond , //not to be used directly - utc , - TOTAL_SIZE - }; - - enum utcType { - UTC_UNKNOWN = 0, - UTC_STD , // set in parse() or normalize() - UTC_POS , // set in parse() - UTC_NEG // set in parse() - }; - - enum timezoneIndex { - hh = 0, - mm , - TIMEZONE_ARRAYSIZE - }; - - static int compareResult(int, int, bool); - static void addDuration(DateTime* pDuration, const DateTime* const pBaseDate, int index); - static int compareResult(const DateTime* const, const DateTime* const, bool, int); - static inline int getRetVal(int, int); - - inline void reset(); - //inline void assertBuffer() const; - inline void copy(const DateTime&); - - inline void initParser(); - inline bool isNormalized() const; - - void getDate(); - void getTime(); - void getYearMonth(); - void getTimeZone(const int); - void parseTimeZone(); - - int findUTCSign(const int start); - int indexOf(const int start, const int end, const XMLCh ch) const; - int parseInt(const int start, const int end) const; - int parseIntYear(const int end) const; - double parseMiliSecond(const int start, const int end) const; - - void validateDateTime() const; - void normalize(); - void fillString(XMLCh*& ptr, valueIndex ind, int expLen) const; - int fillYearString(XMLCh*& ptr, valueIndex ind) const; - void searchMiliSeconds(XMLCh*& miliStartPtr, XMLCh*& miliEndPtr) const; - - bool operator==(const DateTime& toCompare) const; - - static const int DATETIMES[][TOTAL_SIZE]; - int fValue[TOTAL_SIZE]; - int fTimeZone[TIMEZONE_ARRAYSIZE]; - int fStart; - int fEnd; - int fBufferMaxLen; - XMLCh* fBuffer; - - double fMiliSecond; - bool fHasTime; - }; - - inline void DateTime::setBuffer(const XMLCh* const aString) - { - reset(); - fEnd = XMLString::stringLen(aString); - if (fEnd > 0) { - if (fEnd > fBufferMaxLen) { - delete[] fBuffer; - fBufferMaxLen = fEnd + 8; - fBuffer = new XMLCh[fBufferMaxLen+1]; - } - memcpy(fBuffer, aString, (fEnd+1) * sizeof(XMLCh)); - } - } - - inline void DateTime::reset() - { - for ( int i=0; i < XMLDateTime::TOTAL_SIZE; i++ ) - fValue[i] = 0; - - fMiliSecond = 0; - fHasTime = false; - fTimeZone[hh] = fTimeZone[mm] = 0; - fStart = fEnd = 0; - - if (fBuffer) - *fBuffer = 0; - } - - inline void DateTime::copy(const DateTime& rhs) - { - for ( int i = 0; i < XMLDateTime::TOTAL_SIZE; i++ ) - fValue[i] = rhs.fValue[i]; - - fMiliSecond = rhs.fMiliSecond; - fHasTime = rhs.fHasTime; - fTimeZone[hh] = rhs.fTimeZone[hh]; - fTimeZone[mm] = rhs.fTimeZone[mm]; - fStart = rhs.fStart; - fEnd = rhs.fEnd; - - if (fEnd > 0) { - if (fEnd > fBufferMaxLen) { - delete[] fBuffer; - fBufferMaxLen = rhs.fBufferMaxLen; - fBuffer = new XMLCh[fBufferMaxLen+1]; - } - memcpy(fBuffer, rhs.fBuffer, (fEnd+1) * sizeof(XMLCh)); - } - } - - inline void DateTime::initParser() - { - fStart = 0; // to ensure scan from the very first beginning - // in case the pointer is updated accidentally by someone else. - } - - inline bool DateTime::isNormalized() const - { - return (fValue[XMLDateTime::utc] == XMLDateTime::UTC_STD ? true : false); - } - - inline int DateTime::getRetVal(int c1, int c2) - { - if ((c1 == XMLDateTime::LESS_THAN && c2 == XMLDateTime::GREATER_THAN) || - (c1 == XMLDateTime::GREATER_THAN && c2 == XMLDateTime::LESS_THAN)) - return XMLDateTime::INDETERMINATE; - - return (c1 != XMLDateTime::INDETERMINATE) ? c1 : c2; - } - -} - -#endif +/* + * 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 DateTime.h + * + * Manipulation of XML date/time data. + */ + +#ifndef _XML_DATETIME_H +#define _XML_DATETIME_H + +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4244 ) +#endif + +#include + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +namespace xmltooling +{ + /** + * Class for manipulating XML date/time information. + * + * This is mostly copied from Xerces-C, but they haven't produced a usable date/time + * class, so we had to incorporate a version of it for now. It can't be inherited + * since the fields needed are private. + */ + class XMLTOOL_API DateTime + { + public: + /// @cond OFF + DateTime(); + DateTime(const XMLCh* const); + DateTime(time_t epoch); + DateTime(const DateTime&); + DateTime& operator=(const DateTime&); + ~DateTime(); + + inline void setBuffer(const XMLCh* const); + + const XMLCh* getRawData() const; + const XMLCh* getFormattedString() const; + int getSign() const; + + XMLCh* getDateTimeCanonicalRepresentation() const; + XMLCh* getTimeCanonicalRepresentation() const; + + void parseDateTime(); + void parseDate(); + void parseTime(); + void parseDay(); + void parseMonth(); + void parseYear(); + void parseMonthDay(); + void parseYearMonth(); + void parseDuration(); + + static int compare(const DateTime* const, const DateTime* const); + static int compare(const DateTime* const, const DateTime* const, bool); + static int compareOrder(const DateTime* const, const DateTime* const); + + int getYear() const {return fValue[CentYear];} + int getMonth() const {return fValue[Month];} + int getDay() const {return fValue[Day];} + int getHour() const {return fValue[Hour];} + int getMinute() const {return fValue[Minute];} + int getSecond() const {return fValue[Second];} + time_t getEpoch() const; + + /// @endcond + private: + enum valueIndex { + CentYear = 0, + Month , + Day , + Hour , + Minute , + Second , + MiliSecond , //not to be used directly + utc , + TOTAL_SIZE + }; + + enum utcType { + UTC_UNKNOWN = 0, + UTC_STD , // set in parse() or normalize() + UTC_POS , // set in parse() + UTC_NEG // set in parse() + }; + + enum timezoneIndex { + hh = 0, + mm , + TIMEZONE_ARRAYSIZE + }; + + static int compareResult(int, int, bool); + static void addDuration(DateTime* pDuration, const DateTime* const pBaseDate, int index); + static int compareResult(const DateTime* const, const DateTime* const, bool, int); + static inline int getRetVal(int, int); + + inline void reset(); + //inline void assertBuffer() const; + inline void copy(const DateTime&); + + inline void initParser(); + inline bool isNormalized() const; + + void getDate(); + void getTime(); + void getYearMonth(); + void getTimeZone(const int); + void parseTimeZone(); + + int findUTCSign(const int start); + int indexOf(const int start, const int end, const XMLCh ch) const; + int parseInt(const int start, const int end) const; + int parseIntYear(const int end) const; + double parseMiliSecond(const int start, const int end) const; + + void validateDateTime() const; + void normalize(); + void fillString(XMLCh*& ptr, valueIndex ind, int expLen) const; + int fillYearString(XMLCh*& ptr, valueIndex ind) const; + void searchMiliSeconds(XMLCh*& miliStartPtr, XMLCh*& miliEndPtr) const; + + bool operator==(const DateTime& toCompare) const; + + static const int DATETIMES[][TOTAL_SIZE]; + int fValue[TOTAL_SIZE]; + int fTimeZone[TIMEZONE_ARRAYSIZE]; + int fStart; + int fEnd; + int fBufferMaxLen; + XMLCh* fBuffer; + + double fMiliSecond; + bool fHasTime; + }; + + inline void DateTime::setBuffer(const XMLCh* const aString) + { + reset(); + fEnd = XMLString::stringLen(aString); + if (fEnd > 0) { + if (fEnd > fBufferMaxLen) { + delete[] fBuffer; + fBufferMaxLen = fEnd + 8; + fBuffer = new XMLCh[fBufferMaxLen+1]; + } + memcpy(fBuffer, aString, (fEnd+1) * sizeof(XMLCh)); + } + } + + inline void DateTime::reset() + { + for ( int i=0; i < XMLDateTime::TOTAL_SIZE; i++ ) + fValue[i] = 0; + + fMiliSecond = 0; + fHasTime = false; + fTimeZone[hh] = fTimeZone[mm] = 0; + fStart = fEnd = 0; + + if (fBuffer) + *fBuffer = 0; + } + + inline void DateTime::copy(const DateTime& rhs) + { + for ( int i = 0; i < XMLDateTime::TOTAL_SIZE; i++ ) + fValue[i] = rhs.fValue[i]; + + fMiliSecond = rhs.fMiliSecond; + fHasTime = rhs.fHasTime; + fTimeZone[hh] = rhs.fTimeZone[hh]; + fTimeZone[mm] = rhs.fTimeZone[mm]; + fStart = rhs.fStart; + fEnd = rhs.fEnd; + + if (fEnd > 0) { + if (fEnd > fBufferMaxLen) { + delete[] fBuffer; + fBufferMaxLen = rhs.fBufferMaxLen; + fBuffer = new XMLCh[fBufferMaxLen+1]; + } + memcpy(fBuffer, rhs.fBuffer, (fEnd+1) * sizeof(XMLCh)); + } + } + + inline void DateTime::initParser() + { + fStart = 0; // to ensure scan from the very first beginning + // in case the pointer is updated accidentally by someone else. + } + + inline bool DateTime::isNormalized() const + { + return (fValue[XMLDateTime::utc] == XMLDateTime::UTC_STD ? true : false); + } + + inline int DateTime::getRetVal(int c1, int c2) + { + if ((c1 == XMLDateTime::LESS_THAN && c2 == XMLDateTime::GREATER_THAN) || + (c1 == XMLDateTime::GREATER_THAN && c2 == XMLDateTime::LESS_THAN)) + return XMLDateTime::INDETERMINATE; + + return (c1 != XMLDateTime::INDETERMINATE) ? c1 : c2; + } + +} + +#endif diff --git a/xmltooling/util/NDC.cpp b/xmltooling/util/NDC.cpp index 966fb30..2867a4c 100644 --- a/xmltooling/util/NDC.cpp +++ b/xmltooling/util/NDC.cpp @@ -1,43 +1,43 @@ -/* - * 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. - */ - -/** - * NDC.cpp - * - * Diagnostic context for logging - */ - -#include "internal.h" -#include "util/NDC.h" - -#include - -using namespace xmltooling; - -NDC::NDC(const char* context) -{ - log4cpp::NDC::push(context); -} - -NDC::NDC(const std::string& context) -{ - log4cpp::NDC::push(context); -} - -NDC::~NDC() -{ - log4cpp::NDC::pop(); -} +/* + * 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. + */ + +/** + * NDC.cpp + * + * Diagnostic context for logging + */ + +#include "internal.h" +#include "util/NDC.h" + +#include + +using namespace xmltooling; + +NDC::NDC(const char* context) +{ + log4cpp::NDC::push(context); +} + +NDC::NDC(const std::string& context) +{ + log4cpp::NDC::push(context); +} + +NDC::~NDC() +{ + log4cpp::NDC::pop(); +} diff --git a/xmltooling/util/NDC.h b/xmltooling/util/NDC.h index 9d5714c..eb5de13 100644 --- a/xmltooling/util/NDC.h +++ b/xmltooling/util/NDC.h @@ -1,59 +1,59 @@ -/* - * 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 NDC.h - * - * Diagnostic context for logging - */ - -#if !defined(__xmltooling_ndc_h__) -#define __xmltooling_ndc_h__ - -#include -#include - -namespace xmltooling { - - /** - * A portable stack-based context for diagnostic logging - */ - class XMLTOOL_API NDC - { - public: - /** - * Constructor pushes logging context onto diagnostic stack - * @param context null-terminated label for context - */ - NDC(const char* context); - - /** - * Constructor pushes logging context onto diagnostic stack - * @param context string label for context - */ - NDC(const std::string& context); - - /** - * Destructor pops context off of diagnostic stack - */ - ~NDC(); - - MAKE_NONCOPYABLE(NDC); - }; - -}; - -#endif /* __xmltooling_ndc_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 NDC.h + * + * Diagnostic context for logging + */ + +#if !defined(__xmltooling_ndc_h__) +#define __xmltooling_ndc_h__ + +#include +#include + +namespace xmltooling { + + /** + * A portable stack-based context for diagnostic logging + */ + class XMLTOOL_API NDC + { + public: + /** + * Constructor pushes logging context onto diagnostic stack + * @param context null-terminated label for context + */ + NDC(const char* context); + + /** + * Constructor pushes logging context onto diagnostic stack + * @param context string label for context + */ + NDC(const std::string& context); + + /** + * Destructor pops context off of diagnostic stack + */ + ~NDC(); + + MAKE_NONCOPYABLE(NDC); + }; + +}; + +#endif /* __xmltooling_ndc_h__ */ diff --git a/xmltooling/util/ParserPool.h b/xmltooling/util/ParserPool.h index 64910df..f4f9a8f 100644 --- a/xmltooling/util/ParserPool.h +++ b/xmltooling/util/ParserPool.h @@ -1,185 +1,185 @@ -/* - * 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 ParserPool.h - * - * XML parsing - */ - -#if !defined(__xmltooling_pool_h__) -#define __xmltooling_pool_h__ - -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace xercesc; - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * A thread-safe pool of DOMBuilders that share characteristics - */ - class XMLTOOL_API ParserPool : public DOMEntityResolver, DOMErrorHandler - { - MAKE_NONCOPYABLE(ParserPool); - public: - /** - * Constructs a new pool - * - * @param namespaceAware indicates whether parsers should be namespace-aware or not - * @param schemaAware indicates whether parsers should be schema-validating or not - */ - ParserPool(bool namespaceAware=true, bool schemaAware=false); - ~ParserPool(); - - /** - * Creates a new document using a parser from this pool. - * - * @return new XML document - * - */ - DOMDocument* newDocument(); - - /** - * Parses a document using a pooled parser with the proper settings - * - * @param domsrc A DOM source containing the content to be parsed - * @return The DOM document resulting from the parse - * @throws XMLParserException thrown if there was a problem reading, parsing, or validating the XML - */ - DOMDocument* parse(DOMInputSource& domsrc); - - /** - * Parses a document using a pooled parser with the proper settings - * - * @param is An input stream containing the content to be parsed - * @return The DOM document resulting from the parse - * @throws XMLParserException thrown if there was a problem reading, parsing, or validating the XML - */ - DOMDocument* parse(std::istream& is); - - /** - * Load an OASIS catalog file to map schema namespace URIs to filenames. - * - * This does not provide real catalog support; only the <uri> element - * is supported to map from a namespace URI to a relative path or file:// URI. - * - * @param pathname path to a catalog file - * @return true iff the catalog was successfully processed - */ - bool loadCatalog(const XMLCh* pathname); - - /** - * Load a schema explicitly from a local file. - * - * Note that "successful processing" does not imply that the schema is valid, - * only that a reference to it was successfully registered with the pool. - * - * @param nsURI XML namespace to load - * @param pathname path to schema file - * @return true iff the schema was successfully processed - */ - bool loadSchema(const XMLCh* nsURI, const XMLCh* pathname); - - /** - * Supplies all external entities (primarily schemas) to the parser - */ - DOMInputSource* resolveEntity(const XMLCh* const publicId, const XMLCh* const systemId, const XMLCh* const baseURI); - - /** - * Handles parsing errors - */ - bool handleError(const DOMError& e); - - private: - DOMBuilder* createBuilder(); - DOMBuilder* checkoutBuilder(); - void checkinBuilder(DOMBuilder* builder); - -#ifdef HAVE_GOOD_STL - xstring m_schemaLocations; - std::map m_schemaLocMap; -#else - std::string m_schemaLocations; - std::map m_schemaLocMap; -#endif - bool m_namespaceAware,m_schemaAware; - std::stack m_pool; - Mutex* m_lock; - }; - - /** - * A parser source that wraps a C++ input stream - */ - class XMLTOOL_API StreamInputSource : public InputSource - { - MAKE_NONCOPYABLE(StreamInputSource); - public: - /** - * Constructs an input source around an input stream reference. - * - * @param is reference to an input stream - * @param systemId optional system identifier to attach to the stream - */ - StreamInputSource(std::istream& is, const char* systemId=NULL) : InputSource(systemId), m_is(is) {} - /// @cond off - virtual BinInputStream* makeStream() const { return new StreamBinInputStream(m_is); } - /// @endcond - - /** - * A Xerces input stream that wraps a C++ input stream - */ - class XMLTOOL_API StreamBinInputStream : public BinInputStream - { - public: - /** - * Constructs a Xerces input stream around a C++ input stream reference. - * - * @param is reference to an input stream - */ - StreamBinInputStream(std::istream& is) : m_is(is), m_pos(0) {} - /// @cond off - virtual unsigned int curPos() const { return m_pos; } - virtual unsigned int readBytes(XMLByte* const toFill, const unsigned int maxToRead); - /// @endcond - private: - std::istream& m_is; - unsigned int m_pos; - }; - - private: - std::istream& m_is; - }; -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_pool_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 ParserPool.h + * + * XML parsing + */ + +#if !defined(__xmltooling_pool_h__) +#define __xmltooling_pool_h__ + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace xercesc; + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * A thread-safe pool of DOMBuilders that share characteristics + */ + class XMLTOOL_API ParserPool : public DOMEntityResolver, DOMErrorHandler + { + MAKE_NONCOPYABLE(ParserPool); + public: + /** + * Constructs a new pool + * + * @param namespaceAware indicates whether parsers should be namespace-aware or not + * @param schemaAware indicates whether parsers should be schema-validating or not + */ + ParserPool(bool namespaceAware=true, bool schemaAware=false); + ~ParserPool(); + + /** + * Creates a new document using a parser from this pool. + * + * @return new XML document + * + */ + DOMDocument* newDocument(); + + /** + * Parses a document using a pooled parser with the proper settings + * + * @param domsrc A DOM source containing the content to be parsed + * @return The DOM document resulting from the parse + * @throws XMLParserException thrown if there was a problem reading, parsing, or validating the XML + */ + DOMDocument* parse(DOMInputSource& domsrc); + + /** + * Parses a document using a pooled parser with the proper settings + * + * @param is An input stream containing the content to be parsed + * @return The DOM document resulting from the parse + * @throws XMLParserException thrown if there was a problem reading, parsing, or validating the XML + */ + DOMDocument* parse(std::istream& is); + + /** + * Load an OASIS catalog file to map schema namespace URIs to filenames. + * + * This does not provide real catalog support; only the <uri> element + * is supported to map from a namespace URI to a relative path or file:// URI. + * + * @param pathname path to a catalog file + * @return true iff the catalog was successfully processed + */ + bool loadCatalog(const XMLCh* pathname); + + /** + * Load a schema explicitly from a local file. + * + * Note that "successful processing" does not imply that the schema is valid, + * only that a reference to it was successfully registered with the pool. + * + * @param nsURI XML namespace to load + * @param pathname path to schema file + * @return true iff the schema was successfully processed + */ + bool loadSchema(const XMLCh* nsURI, const XMLCh* pathname); + + /** + * Supplies all external entities (primarily schemas) to the parser + */ + DOMInputSource* resolveEntity(const XMLCh* const publicId, const XMLCh* const systemId, const XMLCh* const baseURI); + + /** + * Handles parsing errors + */ + bool handleError(const DOMError& e); + + private: + DOMBuilder* createBuilder(); + DOMBuilder* checkoutBuilder(); + void checkinBuilder(DOMBuilder* builder); + +#ifdef HAVE_GOOD_STL + xstring m_schemaLocations; + std::map m_schemaLocMap; +#else + std::string m_schemaLocations; + std::map m_schemaLocMap; +#endif + bool m_namespaceAware,m_schemaAware; + std::stack m_pool; + Mutex* m_lock; + }; + + /** + * A parser source that wraps a C++ input stream + */ + class XMLTOOL_API StreamInputSource : public InputSource + { + MAKE_NONCOPYABLE(StreamInputSource); + public: + /** + * Constructs an input source around an input stream reference. + * + * @param is reference to an input stream + * @param systemId optional system identifier to attach to the stream + */ + StreamInputSource(std::istream& is, const char* systemId=NULL) : InputSource(systemId), m_is(is) {} + /// @cond off + virtual BinInputStream* makeStream() const { return new StreamBinInputStream(m_is); } + /// @endcond + + /** + * A Xerces input stream that wraps a C++ input stream + */ + class XMLTOOL_API StreamBinInputStream : public BinInputStream + { + public: + /** + * Constructs a Xerces input stream around a C++ input stream reference. + * + * @param is reference to an input stream + */ + StreamBinInputStream(std::istream& is) : m_is(is), m_pos(0) {} + /// @cond off + virtual unsigned int curPos() const { return m_pos; } + virtual unsigned int readBytes(XMLByte* const toFill, const unsigned int maxToRead); + /// @endcond + private: + std::istream& m_is; + unsigned int m_pos; + }; + + private: + std::istream& m_is; + }; +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_pool_h__ */ diff --git a/xmltooling/util/ReplayCache.h b/xmltooling/util/ReplayCache.h index 94fd22d..1300d89 100644 --- a/xmltooling/util/ReplayCache.h +++ b/xmltooling/util/ReplayCache.h @@ -1,66 +1,66 @@ -/* - * 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 xmltooling/util/ReplayCache.h - * - * Helper class on top of StorageService for detecting message replay. - */ - -#ifndef __xmltooling_replay_h__ -#define __xmltooling_replay_h__ - -#include - -namespace xmltooling { - - /** - * Helper class on top of StorageService for detecting message replay. - */ - class XMLTOOL_API ReplayCache - { - MAKE_NONCOPYABLE(ReplayCache); - public: - - /** - * Creates a replay cache on top of a particular StorageService. - * - * @param storage pointer to a StorageService, or NULL to keep cache in memory - */ - ReplayCache(StorageService* storage=NULL); - - virtual ~ReplayCache(); - - /** - * Returns true iff the check value is not found in the cache, and stores it. - * - * @param context a context label to subdivide the cache - * @param s value to check - * @param expires time for disposal of value from cache - */ - virtual bool check(const char* context, const char* s, time_t expires); - - bool check(const char* context, const XMLCh* str, time_t expires) { - auto_ptr_char temp(str); - return check(context, temp.get(), expires); - } - - private: - StorageService* m_storage; - }; -}; - -#endif /* __xmltooling_replay_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 xmltooling/util/ReplayCache.h + * + * Helper class on top of StorageService for detecting message replay. + */ + +#ifndef __xmltooling_replay_h__ +#define __xmltooling_replay_h__ + +#include + +namespace xmltooling { + + /** + * Helper class on top of StorageService for detecting message replay. + */ + class XMLTOOL_API ReplayCache + { + MAKE_NONCOPYABLE(ReplayCache); + public: + + /** + * Creates a replay cache on top of a particular StorageService. + * + * @param storage pointer to a StorageService, or NULL to keep cache in memory + */ + ReplayCache(StorageService* storage=NULL); + + virtual ~ReplayCache(); + + /** + * Returns true iff the check value is not found in the cache, and stores it. + * + * @param context a context label to subdivide the cache + * @param s value to check + * @param expires time for disposal of value from cache + */ + virtual bool check(const char* context, const char* s, time_t expires); + + bool check(const char* context, const XMLCh* str, time_t expires) { + auto_ptr_char temp(str); + return check(context, temp.get(), expires); + } + + private: + StorageService* m_storage; + }; +}; + +#endif /* __xmltooling_replay_h__ */ diff --git a/xmltooling/util/StorageService.h b/xmltooling/util/StorageService.h index 571b86d..c96021b 100644 --- a/xmltooling/util/StorageService.h +++ b/xmltooling/util/StorageService.h @@ -1,176 +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. - */ - -/** - * @file xmltooling/util/StorageService.h - * - * Generic data storage interface - */ - -#ifndef __xmltooling_storage_h__ -#define __xmltooling_storage_h__ - -#include - -#include - -namespace xmltooling { - - /** - * Generic data storage facility for use by services that require - * some degree of persistence. Implementations will vary in how much - * persistence they can supply. - * - *

Storage is divided into "contexts" identified by a string label. - * Keys need to be unique only within a given context, so multiple - * components can share a single storage service safely as long as they - * use different labels. - */ - class XMLTOOL_API StorageService - { - MAKE_NONCOPYABLE(StorageService); - public: - virtual ~StorageService() {} - - /** - * Creates a new "short" record in the storage service. - * - * @param context a storage context label - * @param key null-terminated unique key of up to 255 bytes - * @param value null-terminated value of up to 255 bytes to store - * @param expiration an expiration timestamp, after which the record can be purged - * - * @throws IOException raised if errors occur in the insertion process - */ - virtual void createString(const char* context, const char* key, const char* value, time_t expiration)=0; - - /** - * Returns an existing "short" record from the storage service. - * - * @param context a storage context label - * @param key null-terminated unique key of up to 255 bytes - * @param pvalue location in which to return the record value - * @param pexpiration location in which to return the expiration timestamp - * @return true iff a valid record exists and was returned - * - * @throws IOException raised if errors occur in the read process - */ - virtual bool readString(const char* context, const char* key, std::string* pvalue=NULL, time_t* pexpiration=NULL)=0; - - /** - * Updates an existing "short" record in the storage service. - * - * @param context a storage context label - * @param key null-terminated unique key of up to 255 bytes - * @param value null-terminated value of up to 255 bytes to store, or NULL to leave alone - * @param expiration a new expiration timestamp, or 0 to leave alone - * @return true iff the record exists and was updated - * - * @throws IOException raised if errors occur in the update process - */ - virtual bool updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0)=0; - - /** - * Deletes an existing "short" record from the storage service. - * - * @param context a storage context label - * @param key null-terminated unique key of up to 255 bytes - * @return true iff the record existed and was deleted - * - * @throws IOException raised if errors occur in the deletion process - */ - virtual bool deleteString(const char* context, const char* key)=0; - - /** - * Creates a new "long" record in the storage service. - * - * @param context a storage context label - * @param key null-terminated unique key of up to 255 bytes - * @param value null-terminated value of arbitrary length - * @param expiration an expiration timestamp, after which the record can be purged - * - * @throws IOException raised if errors occur in the insertion process - */ - virtual void createText(const char* context, const char* key, const char* value, time_t expiration)=0; - - /** - * Returns an existing "long" record from the storage service. - * - * @param context a storage context label - * @param key null-terminated unique key of up to 255 bytes - * @param pvalue location in which to return the record value - * @param pexpiration location in which to return the expiration timestamp - * @return true iff a valid record exists and was returned - * - * @throws IOException raised if errors occur in the read process - */ - virtual bool readText(const char* context, const char* key, std::string* pvalue=NULL, time_t* pexpiration=NULL)=0; - - /** - * Updates an existing "long" record in the storage service. - * - * @param context a storage context label - * @param key null-terminated unique key of up to 255 bytes - * @param value null-terminated value of arbitrary length to store, or NULL to leave alone - * @param expiration a new expiration timestamp, or 0 to leave alone - * @return true iff the record exists and was updated - * - * @throws IOException raised if errors occur in the update process - */ - virtual bool updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0)=0; - - /** - * Deletes an existing "long" record from the storage service. - * - * @param context a storage context label - * @param key null-terminated unique key of up to 255 bytes - * @return true iff the record existed and was deleted - * - * @throws IOException raised if errors occur in the deletion process - */ - virtual bool deleteText(const char* context, const char* key)=0; - - /** - * Manually trigger a cleanup of expired records. - * The method MAY return without guaranteeing that - * cleanup has already occurred. - * - * @param context a storage context label - */ - virtual void reap(const char* context)=0; - - /** - * Forcibly removes all records in a given context along with any - * associated resources devoted to maintaining the context. - * - * @param context a storage context label - */ - virtual void deleteContext(const char* context)=0; - - protected: - StorageService() {} - }; - - /** - * Registers StorageService classes into the runtime. - */ - void XMLTOOL_API registerStorageServices(); - - /** StorageService based on in-memory caching. */ - #define MEMORY_STORAGE_SERVICE "org.opensaml.xmlooling.MemoryStorageService" -}; - -#endif /* __xmltooling_storage_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 xmltooling/util/StorageService.h + * + * Generic data storage interface + */ + +#ifndef __xmltooling_storage_h__ +#define __xmltooling_storage_h__ + +#include + +#include + +namespace xmltooling { + + /** + * Generic data storage facility for use by services that require + * some degree of persistence. Implementations will vary in how much + * persistence they can supply. + * + *

Storage is divided into "contexts" identified by a string label. + * Keys need to be unique only within a given context, so multiple + * components can share a single storage service safely as long as they + * use different labels. + */ + class XMLTOOL_API StorageService + { + MAKE_NONCOPYABLE(StorageService); + public: + virtual ~StorageService() {} + + /** + * Creates a new "short" record in the storage service. + * + * @param context a storage context label + * @param key null-terminated unique key of up to 255 bytes + * @param value null-terminated value of up to 255 bytes to store + * @param expiration an expiration timestamp, after which the record can be purged + * + * @throws IOException raised if errors occur in the insertion process + */ + virtual void createString(const char* context, const char* key, const char* value, time_t expiration)=0; + + /** + * Returns an existing "short" record from the storage service. + * + * @param context a storage context label + * @param key null-terminated unique key of up to 255 bytes + * @param pvalue location in which to return the record value + * @param pexpiration location in which to return the expiration timestamp + * @return true iff a valid record exists and was returned + * + * @throws IOException raised if errors occur in the read process + */ + virtual bool readString(const char* context, const char* key, std::string* pvalue=NULL, time_t* pexpiration=NULL)=0; + + /** + * Updates an existing "short" record in the storage service. + * + * @param context a storage context label + * @param key null-terminated unique key of up to 255 bytes + * @param value null-terminated value of up to 255 bytes to store, or NULL to leave alone + * @param expiration a new expiration timestamp, or 0 to leave alone + * @return true iff the record exists and was updated + * + * @throws IOException raised if errors occur in the update process + */ + virtual bool updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0)=0; + + /** + * Deletes an existing "short" record from the storage service. + * + * @param context a storage context label + * @param key null-terminated unique key of up to 255 bytes + * @return true iff the record existed and was deleted + * + * @throws IOException raised if errors occur in the deletion process + */ + virtual bool deleteString(const char* context, const char* key)=0; + + /** + * Creates a new "long" record in the storage service. + * + * @param context a storage context label + * @param key null-terminated unique key of up to 255 bytes + * @param value null-terminated value of arbitrary length + * @param expiration an expiration timestamp, after which the record can be purged + * + * @throws IOException raised if errors occur in the insertion process + */ + virtual void createText(const char* context, const char* key, const char* value, time_t expiration)=0; + + /** + * Returns an existing "long" record from the storage service. + * + * @param context a storage context label + * @param key null-terminated unique key of up to 255 bytes + * @param pvalue location in which to return the record value + * @param pexpiration location in which to return the expiration timestamp + * @return true iff a valid record exists and was returned + * + * @throws IOException raised if errors occur in the read process + */ + virtual bool readText(const char* context, const char* key, std::string* pvalue=NULL, time_t* pexpiration=NULL)=0; + + /** + * Updates an existing "long" record in the storage service. + * + * @param context a storage context label + * @param key null-terminated unique key of up to 255 bytes + * @param value null-terminated value of arbitrary length to store, or NULL to leave alone + * @param expiration a new expiration timestamp, or 0 to leave alone + * @return true iff the record exists and was updated + * + * @throws IOException raised if errors occur in the update process + */ + virtual bool updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0)=0; + + /** + * Deletes an existing "long" record from the storage service. + * + * @param context a storage context label + * @param key null-terminated unique key of up to 255 bytes + * @return true iff the record existed and was deleted + * + * @throws IOException raised if errors occur in the deletion process + */ + virtual bool deleteText(const char* context, const char* key)=0; + + /** + * Manually trigger a cleanup of expired records. + * The method MAY return without guaranteeing that + * cleanup has already occurred. + * + * @param context a storage context label + */ + virtual void reap(const char* context)=0; + + /** + * Forcibly removes all records in a given context along with any + * associated resources devoted to maintaining the context. + * + * @param context a storage context label + */ + virtual void deleteContext(const char* context)=0; + + protected: + StorageService() {} + }; + + /** + * Registers StorageService classes into the runtime. + */ + void XMLTOOL_API registerStorageServices(); + + /** StorageService based on in-memory caching. */ + #define MEMORY_STORAGE_SERVICE "org.opensaml.xmlooling.MemoryStorageService" +}; + +#endif /* __xmltooling_storage_h__ */ diff --git a/xmltooling/util/Win32Threads.cpp b/xmltooling/util/Win32Threads.cpp index 8e5cdc0..1111f4d 100644 --- a/xmltooling/util/Win32Threads.cpp +++ b/xmltooling/util/Win32Threads.cpp @@ -1,409 +1,409 @@ -/* - * 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. - */ - -/** - * Win32Threads.cpp - * - * Thread and locking wrappers for Win32 platforms - */ - -#include "internal.h" -#include "util/Threads.h" - -#include - -#ifndef WIN32 -# error "This implementation is for WIN32 platforms." -#endif - -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -// base error code for a routine to return on failure -#define THREAD_ERROR_TIMEOUT (1) -#define THREAD_ERROR_WAKE_OTHER (2) -#define THREAD_ERROR (3) - -// windows returns non zero for success pthreads returns zero -static int XMLTOOL_DLLLOCAL map_windows_error_status_to_pthreads(int rc=0) { - if(rc!=0) // success? - return 0; - Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("error from thread operation (%d)", GetLastError()); - return THREAD_ERROR; -} - -namespace xmltooling { - - // two levels of classes are needed here - // in case InitializeCriticalSection - // throws an exception we can keep from - // calling the critical_section destructor - // on unitilized data, or it could be done with a flag - struct XMLTOOL_DLLLOCAL critical_section_data { - CRITICAL_SECTION cs; - critical_section_data(){ - InitializeCriticalSection(&cs); - } - }; - - class XMLTOOL_DLLLOCAL critical_section { - private: - critical_section_data cse; - public: - critical_section(){} - ~critical_section(){ - DeleteCriticalSection (&cse.cs); - } - void enter(void) { - EnterCriticalSection(&cse.cs); - } - void leave(void) { - LeaveCriticalSection(&cse.cs); - } - }; - - // hold a critical section over the lifetime of this object - // used to make a stack variable that unlocks automaticly - // on return/throw - class XMLTOOL_DLLLOCAL with_crit_section { - private: - critical_section& cs; - public: - with_crit_section(critical_section& acs):cs(acs){ - cs.enter(); - } - ~with_crit_section(){ - cs.leave(); - } - }; - - class XMLTOOL_DLLLOCAL ThreadImpl : public Thread { - private: - HANDLE thread_id; - public: - ThreadImpl(void* (*start_routine)(void*), void* arg) : thread_id(0) { - thread_id=CreateThread( - 0, // security attributes - 0, // use default stack size, maybe this should be setable - (LPTHREAD_START_ROUTINE ) start_routine, - arg, - 0, // flags, default is ignore stacksize and don't create suspended which is what we want - 0); - if (thread_id==0) { - map_windows_error_status_to_pthreads(); - throw ThreadingException("Thread creation failed."); - } - } - - ~ThreadImpl() { - (void)detach(); - } - - int detach() { - if (thread_id==0) - return THREAD_ERROR; - int rc=map_windows_error_status_to_pthreads(CloseHandle(thread_id)); - thread_id=0; - return rc; - } - - int join(void** thread_return) { - if (thread_id==0) - return THREAD_ERROR; - if (thread_return!=0) - *thread_return=0; - int rc=WaitForSingleObject(thread_id,INFINITE); - switch(rc) { - case WAIT_OBJECT_0: - if (thread_return) - map_windows_error_status_to_pthreads(GetExitCodeThread(thread_id,(unsigned long*)thread_return)); - default: - return THREAD_ERROR; - } - return 0; - } - - int kill(int signo) { - if (thread_id==0) - return THREAD_ERROR; - return map_windows_error_status_to_pthreads(TerminateThread(thread_id,signo)); - } - }; - - class XMLTOOL_DLLLOCAL MutexImpl : public Mutex { - private: - HANDLE mhandle; - public: - MutexImpl() : mhandle(CreateMutex(0,false,0)) { - if (mhandle==0) { - map_windows_error_status_to_pthreads(); - throw ThreadingException("Mutex creation failed."); - } - } - - ~MutexImpl() { - if((mhandle!=0) && (!CloseHandle(mhandle))) - map_windows_error_status_to_pthreads(); - } - - int lock() { - int rc=WaitForSingleObject(mhandle,INFINITE); - switch(rc) { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: - return 0; - default: - return map_windows_error_status_to_pthreads(); - } - } - - int unlock() { - return map_windows_error_status_to_pthreads(ReleaseMutex(mhandle)); - } - }; - - class XMLTOOL_DLLLOCAL CondWaitImpl : public CondWait { - private: - HANDLE cond; - - public: - CondWaitImpl() : cond(CreateEvent(0,false,false,0)) { - if(cond==0) { - map_windows_error_status_to_pthreads(); - throw ThreadingException("Event creation failed."); - } - }; - - ~CondWaitImpl() { - if((cond!=0) && (!CloseHandle(cond))) - map_windows_error_status_to_pthreads(); - } - - int wait(Mutex* mutex) { - return timedwait(mutex,INFINITE); - } - - int signal() { - if(!SetEvent(cond)) - return map_windows_error_status_to_pthreads(); - return 0; - } - - int broadcast() { - throw ThreadingException("Broadcast not implemented on Win32 platforms."); - } - - // wait for myself to signal and this mutex or the timeout - int timedwait(Mutex* mutex, int delay_seconds) { - int rc=mutex->unlock(); - if(rc!=0) - return rc; - - int delay_ms=delay_seconds; - if(delay_seconds!=INFINITE) - delay_ms*=1000; - rc=WaitForSingleObject(cond,delay_ms); - int rc2=mutex->lock(); - if(rc2!=0) - return rc2; - switch(rc) { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: - case WAIT_TIMEOUT: - return 0; - default: - return map_windows_error_status_to_pthreads(); - } - return 0; - } - }; - - class XMLTOOL_DLLLOCAL RWLockImpl : public RWLock { - private: - // used to protect read or write to the data below - critical_section cs; - // event handle threads wait on when the lock they want is busy - // normally set to signaled all the time, if some thread can't get what - // they want they reset it and sleep. on releasing a lock set it to - // signaled if someone may have wanted what you just released - HANDLE wake_waiters; - // number of threads holding a read lock - int num_readers; - // true iff there a writer has our lock - bool have_writer; - - public: - RWLockImpl() : wake_waiters(0), num_readers(0), have_writer(true) { - with_crit_section acs(cs); - wake_waiters=CreateEvent(0,true,true,0); - have_writer=false; - if (wake_waiters==0) { - map_windows_error_status_to_pthreads(); - throw ThreadingException("Event creation for shared lock failed."); - } - } - - ~RWLockImpl() { - with_crit_section acs(cs); - if ((wake_waiters!=0) && (!CloseHandle(wake_waiters))) - map_windows_error_status_to_pthreads(); - } - - int rdlock() { - while(1) { - // wait for the lock maybe being availible - // we will find out for sure inside the critical section - if (WaitForSingleObject(wake_waiters,INFINITE)!=WAIT_OBJECT_0) - return map_windows_error_status_to_pthreads(); - - with_crit_section alock(cs); - // invariant not locked for reading and writing - if ((num_readers!=0) && (have_writer)) - return THREAD_ERROR; - // if no writer we can join any existing readers - if (!have_writer) { - num_readers++; - return 0; - } - - // have a writer, mark the synchronization object - // so everyone waits, when the writer unlocks it will wake us - if (!ResetEvent(wake_waiters)) - return map_windows_error_status_to_pthreads(); - } - return THREAD_ERROR; - } - - int wrlock() { - while(1) { - // wait for the lock maybe being availible - // we will find out for sure inside the critical section - if (WaitForSingleObject(wake_waiters,INFINITE)!=WAIT_OBJECT_0) - return map_windows_error_status_to_pthreads(); - - with_crit_section bla(cs); - // invariant not locked for reading and writing - if ((num_readers!=0) && (have_writer)) - return THREAD_ERROR; - - // if no writer and no readers we can become the writer - if ((num_readers==0) && (!have_writer)) { - have_writer=true; - return 0; - } - - // lock is busy, the unlocker will wake us - if (!ResetEvent(wake_waiters)) - return map_windows_error_status_to_pthreads(); - } - return THREAD_ERROR; - } - - int unlock() { - with_crit_section mumble(cs); - // invariant not locked for reading and writing - if ((num_readers!=0) && (have_writer)) - return THREAD_ERROR; - - // error if nothing locked - if ((num_readers==0) && (!have_writer)) - return THREAD_ERROR; - - // if there was a writer it has to be us so unlock write lock - have_writer=false; - - // if there where any reades there is one less now - if(num_readers>0) - num_readers--; - - // if no readers left wake up any readers/writers waiting - // to have a go at it - if (num_readers==0) - if (!SetEvent(wake_waiters)) - return map_windows_error_status_to_pthreads(); - return 0; - } - }; - - typedef void (*destroy_hook_type)(void*); - - class XMLTOOL_DLLLOCAL ThreadKeyImpl : public ThreadKey { - private: - destroy_hook_type destroy_hook; - DWORD key; - - public: - ThreadKeyImpl(void (*destroy_fcn)(void*)) : destroy_hook(destroy_fcn) { - key=TlsAlloc(); - }; - - virtual ~ThreadKeyImpl() { - if (destroy_hook) - destroy_hook(TlsGetValue(key)); - TlsFree(key); - } - - int setData(void* data) { - TlsSetValue(key,data); - return 0; - } - - void* getData() const { - return TlsGetValue(key); - } - }; - -}; - -// -// public "static" creation functions -// - -Thread* Thread::create(void* (*start_routine)(void*), void* arg) -{ - return new ThreadImpl(start_routine, arg); -} - -void Thread::exit(void* return_val) -{ - ExitThread((DWORD)return_val); -} - -void Thread::sleep(int seconds) -{ - Sleep(seconds * 1000); -} - -Mutex * Mutex::create() -{ - return new MutexImpl(); -} - -CondWait * CondWait::create() -{ - return new CondWaitImpl(); -} - -RWLock * RWLock::create() -{ - return new RWLockImpl(); -} - -ThreadKey* ThreadKey::create (void (*destroy_fcn)(void*)) -{ - return new ThreadKeyImpl(destroy_fcn); -} +/* + * 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. + */ + +/** + * Win32Threads.cpp + * + * Thread and locking wrappers for Win32 platforms + */ + +#include "internal.h" +#include "util/Threads.h" + +#include + +#ifndef WIN32 +# error "This implementation is for WIN32 platforms." +#endif + +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +// base error code for a routine to return on failure +#define THREAD_ERROR_TIMEOUT (1) +#define THREAD_ERROR_WAKE_OTHER (2) +#define THREAD_ERROR (3) + +// windows returns non zero for success pthreads returns zero +static int XMLTOOL_DLLLOCAL map_windows_error_status_to_pthreads(int rc=0) { + if(rc!=0) // success? + return 0; + Category::getInstance(XMLTOOLING_LOGCAT".Threads").error("error from thread operation (%d)", GetLastError()); + return THREAD_ERROR; +} + +namespace xmltooling { + + // two levels of classes are needed here + // in case InitializeCriticalSection + // throws an exception we can keep from + // calling the critical_section destructor + // on unitilized data, or it could be done with a flag + struct XMLTOOL_DLLLOCAL critical_section_data { + CRITICAL_SECTION cs; + critical_section_data(){ + InitializeCriticalSection(&cs); + } + }; + + class XMLTOOL_DLLLOCAL critical_section { + private: + critical_section_data cse; + public: + critical_section(){} + ~critical_section(){ + DeleteCriticalSection (&cse.cs); + } + void enter(void) { + EnterCriticalSection(&cse.cs); + } + void leave(void) { + LeaveCriticalSection(&cse.cs); + } + }; + + // hold a critical section over the lifetime of this object + // used to make a stack variable that unlocks automaticly + // on return/throw + class XMLTOOL_DLLLOCAL with_crit_section { + private: + critical_section& cs; + public: + with_crit_section(critical_section& acs):cs(acs){ + cs.enter(); + } + ~with_crit_section(){ + cs.leave(); + } + }; + + class XMLTOOL_DLLLOCAL ThreadImpl : public Thread { + private: + HANDLE thread_id; + public: + ThreadImpl(void* (*start_routine)(void*), void* arg) : thread_id(0) { + thread_id=CreateThread( + 0, // security attributes + 0, // use default stack size, maybe this should be setable + (LPTHREAD_START_ROUTINE ) start_routine, + arg, + 0, // flags, default is ignore stacksize and don't create suspended which is what we want + 0); + if (thread_id==0) { + map_windows_error_status_to_pthreads(); + throw ThreadingException("Thread creation failed."); + } + } + + ~ThreadImpl() { + (void)detach(); + } + + int detach() { + if (thread_id==0) + return THREAD_ERROR; + int rc=map_windows_error_status_to_pthreads(CloseHandle(thread_id)); + thread_id=0; + return rc; + } + + int join(void** thread_return) { + if (thread_id==0) + return THREAD_ERROR; + if (thread_return!=0) + *thread_return=0; + int rc=WaitForSingleObject(thread_id,INFINITE); + switch(rc) { + case WAIT_OBJECT_0: + if (thread_return) + map_windows_error_status_to_pthreads(GetExitCodeThread(thread_id,(unsigned long*)thread_return)); + default: + return THREAD_ERROR; + } + return 0; + } + + int kill(int signo) { + if (thread_id==0) + return THREAD_ERROR; + return map_windows_error_status_to_pthreads(TerminateThread(thread_id,signo)); + } + }; + + class XMLTOOL_DLLLOCAL MutexImpl : public Mutex { + private: + HANDLE mhandle; + public: + MutexImpl() : mhandle(CreateMutex(0,false,0)) { + if (mhandle==0) { + map_windows_error_status_to_pthreads(); + throw ThreadingException("Mutex creation failed."); + } + } + + ~MutexImpl() { + if((mhandle!=0) && (!CloseHandle(mhandle))) + map_windows_error_status_to_pthreads(); + } + + int lock() { + int rc=WaitForSingleObject(mhandle,INFINITE); + switch(rc) { + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + return 0; + default: + return map_windows_error_status_to_pthreads(); + } + } + + int unlock() { + return map_windows_error_status_to_pthreads(ReleaseMutex(mhandle)); + } + }; + + class XMLTOOL_DLLLOCAL CondWaitImpl : public CondWait { + private: + HANDLE cond; + + public: + CondWaitImpl() : cond(CreateEvent(0,false,false,0)) { + if(cond==0) { + map_windows_error_status_to_pthreads(); + throw ThreadingException("Event creation failed."); + } + }; + + ~CondWaitImpl() { + if((cond!=0) && (!CloseHandle(cond))) + map_windows_error_status_to_pthreads(); + } + + int wait(Mutex* mutex) { + return timedwait(mutex,INFINITE); + } + + int signal() { + if(!SetEvent(cond)) + return map_windows_error_status_to_pthreads(); + return 0; + } + + int broadcast() { + throw ThreadingException("Broadcast not implemented on Win32 platforms."); + } + + // wait for myself to signal and this mutex or the timeout + int timedwait(Mutex* mutex, int delay_seconds) { + int rc=mutex->unlock(); + if(rc!=0) + return rc; + + int delay_ms=delay_seconds; + if(delay_seconds!=INFINITE) + delay_ms*=1000; + rc=WaitForSingleObject(cond,delay_ms); + int rc2=mutex->lock(); + if(rc2!=0) + return rc2; + switch(rc) { + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + case WAIT_TIMEOUT: + return 0; + default: + return map_windows_error_status_to_pthreads(); + } + return 0; + } + }; + + class XMLTOOL_DLLLOCAL RWLockImpl : public RWLock { + private: + // used to protect read or write to the data below + critical_section cs; + // event handle threads wait on when the lock they want is busy + // normally set to signaled all the time, if some thread can't get what + // they want they reset it and sleep. on releasing a lock set it to + // signaled if someone may have wanted what you just released + HANDLE wake_waiters; + // number of threads holding a read lock + int num_readers; + // true iff there a writer has our lock + bool have_writer; + + public: + RWLockImpl() : wake_waiters(0), num_readers(0), have_writer(true) { + with_crit_section acs(cs); + wake_waiters=CreateEvent(0,true,true,0); + have_writer=false; + if (wake_waiters==0) { + map_windows_error_status_to_pthreads(); + throw ThreadingException("Event creation for shared lock failed."); + } + } + + ~RWLockImpl() { + with_crit_section acs(cs); + if ((wake_waiters!=0) && (!CloseHandle(wake_waiters))) + map_windows_error_status_to_pthreads(); + } + + int rdlock() { + while(1) { + // wait for the lock maybe being availible + // we will find out for sure inside the critical section + if (WaitForSingleObject(wake_waiters,INFINITE)!=WAIT_OBJECT_0) + return map_windows_error_status_to_pthreads(); + + with_crit_section alock(cs); + // invariant not locked for reading and writing + if ((num_readers!=0) && (have_writer)) + return THREAD_ERROR; + // if no writer we can join any existing readers + if (!have_writer) { + num_readers++; + return 0; + } + + // have a writer, mark the synchronization object + // so everyone waits, when the writer unlocks it will wake us + if (!ResetEvent(wake_waiters)) + return map_windows_error_status_to_pthreads(); + } + return THREAD_ERROR; + } + + int wrlock() { + while(1) { + // wait for the lock maybe being availible + // we will find out for sure inside the critical section + if (WaitForSingleObject(wake_waiters,INFINITE)!=WAIT_OBJECT_0) + return map_windows_error_status_to_pthreads(); + + with_crit_section bla(cs); + // invariant not locked for reading and writing + if ((num_readers!=0) && (have_writer)) + return THREAD_ERROR; + + // if no writer and no readers we can become the writer + if ((num_readers==0) && (!have_writer)) { + have_writer=true; + return 0; + } + + // lock is busy, the unlocker will wake us + if (!ResetEvent(wake_waiters)) + return map_windows_error_status_to_pthreads(); + } + return THREAD_ERROR; + } + + int unlock() { + with_crit_section mumble(cs); + // invariant not locked for reading and writing + if ((num_readers!=0) && (have_writer)) + return THREAD_ERROR; + + // error if nothing locked + if ((num_readers==0) && (!have_writer)) + return THREAD_ERROR; + + // if there was a writer it has to be us so unlock write lock + have_writer=false; + + // if there where any reades there is one less now + if(num_readers>0) + num_readers--; + + // if no readers left wake up any readers/writers waiting + // to have a go at it + if (num_readers==0) + if (!SetEvent(wake_waiters)) + return map_windows_error_status_to_pthreads(); + return 0; + } + }; + + typedef void (*destroy_hook_type)(void*); + + class XMLTOOL_DLLLOCAL ThreadKeyImpl : public ThreadKey { + private: + destroy_hook_type destroy_hook; + DWORD key; + + public: + ThreadKeyImpl(void (*destroy_fcn)(void*)) : destroy_hook(destroy_fcn) { + key=TlsAlloc(); + }; + + virtual ~ThreadKeyImpl() { + if (destroy_hook) + destroy_hook(TlsGetValue(key)); + TlsFree(key); + } + + int setData(void* data) { + TlsSetValue(key,data); + return 0; + } + + void* getData() const { + return TlsGetValue(key); + } + }; + +}; + +// +// public "static" creation functions +// + +Thread* Thread::create(void* (*start_routine)(void*), void* arg) +{ + return new ThreadImpl(start_routine, arg); +} + +void Thread::exit(void* return_val) +{ + ExitThread((DWORD)return_val); +} + +void Thread::sleep(int seconds) +{ + Sleep(seconds * 1000); +} + +Mutex * Mutex::create() +{ + return new MutexImpl(); +} + +CondWait * CondWait::create() +{ + return new CondWaitImpl(); +} + +RWLock * RWLock::create() +{ + return new RWLockImpl(); +} + +ThreadKey* ThreadKey::create (void (*destroy_fcn)(void*)) +{ + return new ThreadKeyImpl(destroy_fcn); +} diff --git a/xmltooling/util/XMLConstants.cpp b/xmltooling/util/XMLConstants.cpp index 232c8d5..a45f7c5 100644 --- a/xmltooling/util/XMLConstants.cpp +++ b/xmltooling/util/XMLConstants.cpp @@ -1,110 +1,110 @@ -/* - * 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. - */ - -/** - * XMLConstants.cpp - * - * Fundamental XML namespace constants - */ - - -#include "internal.h" -#include "util/XMLConstants.h" -#include - -using namespace xmltooling; - -const XMLCh XMLConstants::XML_NS[] = // http://www.w3.org/XML/1998/namespace -{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, - chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, - chLatin_X, chLatin_M, chLatin_L, chForwardSlash, chDigit_1, chDigit_9, chDigit_9, chDigit_8, chForwardSlash, - chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chNull -}; - -const XMLCh XMLConstants::XMLNS_NS[] = // http://www.w3.org/2000/xmlns/ -{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, - chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, - chDigit_2, chDigit_0, chDigit_0, chDigit_0, chForwardSlash, - chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chForwardSlash, chNull -}; - -const XMLCh XMLConstants::XMLNS_PREFIX[] = { chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull }; - -const XMLCh XMLConstants::XML_PREFIX[] = { chLatin_x, chLatin_m, chLatin_l, chNull }; - -const XMLCh XMLConstants::XSD_NS[] = // http://www.w3.org/2001/XMLSchema -{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, - chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, - chDigit_2, chDigit_0, chDigit_0, chDigit_1, chForwardSlash, - chLatin_X, chLatin_M, chLatin_L, chLatin_S, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, chNull -}; - -const XMLCh XMLConstants::XSD_PREFIX[] = { chLatin_x, chLatin_s, chNull }; - -const XMLCh XMLConstants::XSI_NS[] = // http://www.w3.org/2001/XMLSchema-instance -{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, - chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, - chDigit_2, chDigit_0, chDigit_0, chDigit_1, chForwardSlash, - chLatin_X, chLatin_M, chLatin_L, chLatin_S, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, chDash, - chLatin_i, chLatin_n, chLatin_s, chLatin_t, chLatin_a, chLatin_n, chLatin_c, chLatin_e, chNull -}; - -const XMLCh XMLConstants::XSI_PREFIX[] = { chLatin_x, chLatin_s, chLatin_i, chNull }; - -const XMLCh XMLConstants::XMLSIG_NS[] = // http://www.w3.org/2000/09/xmldsig# -{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, - chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, - chDigit_2, chDigit_0, chDigit_0, chDigit_0, chForwardSlash, chDigit_0, chDigit_9, chForwardSlash, - chLatin_x, chLatin_m, chLatin_l, chLatin_d, chLatin_s, chLatin_i, chLatin_g, chPound, chNull -}; - -const XMLCh XMLConstants::XMLSIG_PREFIX[] = { chLatin_d, chLatin_s, chNull }; - -const XMLCh XMLConstants::XMLENC_NS[] = // http://www.w3.org/2001/04/xmlenc# -{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, - chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, - chDigit_2, chDigit_0, chDigit_0, chDigit_1, chForwardSlash, chDigit_0, chDigit_4, chForwardSlash, - chLatin_x, chLatin_m, chLatin_l, chLatin_e, chLatin_n, chLatin_c, chPound, chNull -}; - -const XMLCh XMLConstants::XMLENC_PREFIX[] = { chLatin_x, chLatin_e, chLatin_n, chLatin_c, chNull }; - -const XMLCh XMLConstants::SOAP11ENV_NS[] = // http://schemas.xmlsoap.org/soap/envelope/ -{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, - chLatin_s, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, chLatin_s, chPeriod, - chLatin_x, chLatin_m, chLatin_l, chLatin_s, chLatin_o, chLatin_a, chLatin_p, chPeriod, - chLatin_o, chLatin_r, chLatin_g, chForwardSlash, - chLatin_s, chLatin_o, chLatin_a, chLatin_p, chForwardSlash, - chLatin_e, chLatin_n, chLatin_v, chLatin_e, chLatin_l, chLatin_o, chLatin_p, chLatin_e, chForwardSlash, chNull -}; - -const XMLCh XMLConstants::SOAP11ENV_PREFIX[] = UNICODE_LITERAL_1(S); - -const XMLCh XMLConstants::XMLTOOLING_NS[] = // http://www.opensaml.org/xmltooling -{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, - chLatin_w, chLatin_w, chLatin_w, chPeriod, - chLatin_o, chLatin_p, chLatin_e, chLatin_n, chLatin_s, chLatin_a, chLatin_m, chLatin_l, chPeriod, - chLatin_o, chLatin_r, chLatin_g, chForwardSlash, - chLatin_x, chLatin_m, chLatin_l, chLatin_t, chLatin_o, chLatin_o, chLatin_l, chLatin_i, chLatin_n, chLatin_g, chNull -}; - -const XMLCh XMLConstants::XML_TRUE[] = { chLatin_t, chLatin_r, chLatin_u, chLatin_e, chNull }; - -const XMLCh XMLConstants::XML_FALSE[] = { chLatin_f, chLatin_a, chLatin_l, chLatin_s, chLatin_e, chNull }; - -const XMLCh XMLConstants::XML_ONE[] = { chDigit_1, chNull }; - -const XMLCh XMLConstants::XML_ZERO[] = { chDigit_0, chNull }; +/* + * 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. + */ + +/** + * XMLConstants.cpp + * + * Fundamental XML namespace constants + */ + + +#include "internal.h" +#include "util/XMLConstants.h" +#include + +using namespace xmltooling; + +const XMLCh XMLConstants::XML_NS[] = // http://www.w3.org/XML/1998/namespace +{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, + chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, + chLatin_X, chLatin_M, chLatin_L, chForwardSlash, chDigit_1, chDigit_9, chDigit_9, chDigit_8, chForwardSlash, + chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chNull +}; + +const XMLCh XMLConstants::XMLNS_NS[] = // http://www.w3.org/2000/xmlns/ +{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, + chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, + chDigit_2, chDigit_0, chDigit_0, chDigit_0, chForwardSlash, + chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chForwardSlash, chNull +}; + +const XMLCh XMLConstants::XMLNS_PREFIX[] = { chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull }; + +const XMLCh XMLConstants::XML_PREFIX[] = { chLatin_x, chLatin_m, chLatin_l, chNull }; + +const XMLCh XMLConstants::XSD_NS[] = // http://www.w3.org/2001/XMLSchema +{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, + chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, + chDigit_2, chDigit_0, chDigit_0, chDigit_1, chForwardSlash, + chLatin_X, chLatin_M, chLatin_L, chLatin_S, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, chNull +}; + +const XMLCh XMLConstants::XSD_PREFIX[] = { chLatin_x, chLatin_s, chNull }; + +const XMLCh XMLConstants::XSI_NS[] = // http://www.w3.org/2001/XMLSchema-instance +{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, + chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, + chDigit_2, chDigit_0, chDigit_0, chDigit_1, chForwardSlash, + chLatin_X, chLatin_M, chLatin_L, chLatin_S, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, chDash, + chLatin_i, chLatin_n, chLatin_s, chLatin_t, chLatin_a, chLatin_n, chLatin_c, chLatin_e, chNull +}; + +const XMLCh XMLConstants::XSI_PREFIX[] = { chLatin_x, chLatin_s, chLatin_i, chNull }; + +const XMLCh XMLConstants::XMLSIG_NS[] = // http://www.w3.org/2000/09/xmldsig# +{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, + chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, + chDigit_2, chDigit_0, chDigit_0, chDigit_0, chForwardSlash, chDigit_0, chDigit_9, chForwardSlash, + chLatin_x, chLatin_m, chLatin_l, chLatin_d, chLatin_s, chLatin_i, chLatin_g, chPound, chNull +}; + +const XMLCh XMLConstants::XMLSIG_PREFIX[] = { chLatin_d, chLatin_s, chNull }; + +const XMLCh XMLConstants::XMLENC_NS[] = // http://www.w3.org/2001/04/xmlenc# +{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, + chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash, + chDigit_2, chDigit_0, chDigit_0, chDigit_1, chForwardSlash, chDigit_0, chDigit_4, chForwardSlash, + chLatin_x, chLatin_m, chLatin_l, chLatin_e, chLatin_n, chLatin_c, chPound, chNull +}; + +const XMLCh XMLConstants::XMLENC_PREFIX[] = { chLatin_x, chLatin_e, chLatin_n, chLatin_c, chNull }; + +const XMLCh XMLConstants::SOAP11ENV_NS[] = // http://schemas.xmlsoap.org/soap/envelope/ +{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, + chLatin_s, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_a, chLatin_s, chPeriod, + chLatin_x, chLatin_m, chLatin_l, chLatin_s, chLatin_o, chLatin_a, chLatin_p, chPeriod, + chLatin_o, chLatin_r, chLatin_g, chForwardSlash, + chLatin_s, chLatin_o, chLatin_a, chLatin_p, chForwardSlash, + chLatin_e, chLatin_n, chLatin_v, chLatin_e, chLatin_l, chLatin_o, chLatin_p, chLatin_e, chForwardSlash, chNull +}; + +const XMLCh XMLConstants::SOAP11ENV_PREFIX[] = UNICODE_LITERAL_1(S); + +const XMLCh XMLConstants::XMLTOOLING_NS[] = // http://www.opensaml.org/xmltooling +{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, + chLatin_w, chLatin_w, chLatin_w, chPeriod, + chLatin_o, chLatin_p, chLatin_e, chLatin_n, chLatin_s, chLatin_a, chLatin_m, chLatin_l, chPeriod, + chLatin_o, chLatin_r, chLatin_g, chForwardSlash, + chLatin_x, chLatin_m, chLatin_l, chLatin_t, chLatin_o, chLatin_o, chLatin_l, chLatin_i, chLatin_n, chLatin_g, chNull +}; + +const XMLCh XMLConstants::XML_TRUE[] = { chLatin_t, chLatin_r, chLatin_u, chLatin_e, chNull }; + +const XMLCh XMLConstants::XML_FALSE[] = { chLatin_f, chLatin_a, chLatin_l, chLatin_s, chLatin_e, chNull }; + +const XMLCh XMLConstants::XML_ONE[] = { chDigit_1, chNull }; + +const XMLCh XMLConstants::XML_ZERO[] = { chDigit_0, chNull }; diff --git a/xmltooling/util/XMLConstants.h b/xmltooling/util/XMLConstants.h index 355ec39..093688d 100644 --- a/xmltooling/util/XMLConstants.h +++ b/xmltooling/util/XMLConstants.h @@ -1,104 +1,104 @@ -/* - * 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 XMLConstants.h - * - * Fundamental XML namespace constants - */ - -#if !defined(__xmltooling_xmlconstants_h__) -#define __xmltooling_xmlconstants_h__ - -#include - -namespace xmltooling { - - /** - * XML related constants. - */ - struct XMLTOOL_API XMLConstants - { - /** XML core namespace ("http://www.w3.org/XML/1998/namespace") */ - static const XMLCh XML_NS[]; - - /** XML namespace prefix for special xml attributes ("xml") */ - static const XMLCh XML_PREFIX[]; - - /** XML namespace for xmlns attributes ("http://www.w3.org/2000/xmlns/") */ - static const XMLCh XMLNS_NS[]; - - /** XML namespace prefix for xmlns attributes ("xmlns") */ - static const XMLCh XMLNS_PREFIX[]; - - /** XML Schema namespace ("http://www.w3.org/2001/XMLSchema") */ - static const XMLCh XSD_NS[]; - - /** XML Schema QName prefix ("xs") */ - static const XMLCh XSD_PREFIX[]; - - /** XML Schema Instance namespace ("http://www.w3.org/2001/XMLSchema-instance") */ - static const XMLCh XSI_NS[]; - - /** XML Schema Instance QName prefix ("xsi") */ - static const XMLCh XSI_PREFIX[]; - - /** XML Signature namespace ("http://www.w3.org/2000/09/xmldsig#") */ - static const XMLCh XMLSIG_NS[]; - - /** XML Signature QName prefix ("ds") */ - static const XMLCh XMLSIG_PREFIX[]; - - /** XML Encryption namespace ("http://www.w3.org/2001/04/xmlenc#") */ - static const XMLCh XMLENC_NS[]; - - /** XML Encryption QName prefix ("xenc") */ - static const XMLCh XMLENC_PREFIX[]; - - /** SOAP 1.1 Envelope XML namespace ("http://schemas.xmlsoap.org/soap/envelope/") */ - static const XMLCh SOAP11ENV_NS[]; - - /** SOAP 1.1 Envelope QName prefix ("S") */ - static const XMLCh SOAP11ENV_PREFIX[]; - - /** XML Tooling namespace ("http://www.opensaml.org/xmltooling") */ - static const XMLCh XMLTOOLING_NS[]; - - /** XML "true" boolean constant */ - static const XMLCh XML_TRUE[]; - - /** XML "false" boolean constant */ - static const XMLCh XML_FALSE[]; - - /** XML "1" boolean constant */ - static const XMLCh XML_ONE[]; - - /** XML "0" boolean constant */ - static const XMLCh XML_ZERO[]; - - /** Enumerations of the different values of a boolean attribute or element */ - enum xmltooling_bool_t { - XML_BOOL_NULL, - XML_BOOL_TRUE, - XML_BOOL_FALSE, - XML_BOOL_ONE, - XML_BOOL_ZERO - }; - }; - -}; - -#endif /* __xmltooling_xmlconstants_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 XMLConstants.h + * + * Fundamental XML namespace constants + */ + +#if !defined(__xmltooling_xmlconstants_h__) +#define __xmltooling_xmlconstants_h__ + +#include + +namespace xmltooling { + + /** + * XML related constants. + */ + struct XMLTOOL_API XMLConstants + { + /** XML core namespace ("http://www.w3.org/XML/1998/namespace") */ + static const XMLCh XML_NS[]; + + /** XML namespace prefix for special xml attributes ("xml") */ + static const XMLCh XML_PREFIX[]; + + /** XML namespace for xmlns attributes ("http://www.w3.org/2000/xmlns/") */ + static const XMLCh XMLNS_NS[]; + + /** XML namespace prefix for xmlns attributes ("xmlns") */ + static const XMLCh XMLNS_PREFIX[]; + + /** XML Schema namespace ("http://www.w3.org/2001/XMLSchema") */ + static const XMLCh XSD_NS[]; + + /** XML Schema QName prefix ("xs") */ + static const XMLCh XSD_PREFIX[]; + + /** XML Schema Instance namespace ("http://www.w3.org/2001/XMLSchema-instance") */ + static const XMLCh XSI_NS[]; + + /** XML Schema Instance QName prefix ("xsi") */ + static const XMLCh XSI_PREFIX[]; + + /** XML Signature namespace ("http://www.w3.org/2000/09/xmldsig#") */ + static const XMLCh XMLSIG_NS[]; + + /** XML Signature QName prefix ("ds") */ + static const XMLCh XMLSIG_PREFIX[]; + + /** XML Encryption namespace ("http://www.w3.org/2001/04/xmlenc#") */ + static const XMLCh XMLENC_NS[]; + + /** XML Encryption QName prefix ("xenc") */ + static const XMLCh XMLENC_PREFIX[]; + + /** SOAP 1.1 Envelope XML namespace ("http://schemas.xmlsoap.org/soap/envelope/") */ + static const XMLCh SOAP11ENV_NS[]; + + /** SOAP 1.1 Envelope QName prefix ("S") */ + static const XMLCh SOAP11ENV_PREFIX[]; + + /** XML Tooling namespace ("http://www.opensaml.org/xmltooling") */ + static const XMLCh XMLTOOLING_NS[]; + + /** XML "true" boolean constant */ + static const XMLCh XML_TRUE[]; + + /** XML "false" boolean constant */ + static const XMLCh XML_FALSE[]; + + /** XML "1" boolean constant */ + static const XMLCh XML_ONE[]; + + /** XML "0" boolean constant */ + static const XMLCh XML_ZERO[]; + + /** Enumerations of the different values of a boolean attribute or element */ + enum xmltooling_bool_t { + XML_BOOL_NULL, + XML_BOOL_TRUE, + XML_BOOL_FALSE, + XML_BOOL_ONE, + XML_BOOL_ZERO + }; + }; + +}; + +#endif /* __xmltooling_xmlconstants_h__ */ diff --git a/xmltooling/util/XMLHelper.cpp b/xmltooling/util/XMLHelper.cpp index 1bf8d5d..9411daa 100644 --- a/xmltooling/util/XMLHelper.cpp +++ b/xmltooling/util/XMLHelper.cpp @@ -1,229 +1,229 @@ -/* - * 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. - */ - -/** - * XMLHelper.cpp - * - * A helper class for working with W3C DOM objects. - */ - -#include "internal.h" -#include "exceptions.h" -#include "util/XMLHelper.h" -#include "util/XMLConstants.h" - -#include -#include - -using namespace xmltooling; - -static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull }; - -bool XMLHelper::hasXSIType(const DOMElement* e) -{ - if (e) { - if (e->hasAttributeNS(XMLConstants::XSI_NS, type)) { - return true; - } - } - - return false; -} - -QName* XMLHelper::getXSIType(const DOMElement* e) -{ - DOMAttr* attribute = e->getAttributeNodeNS(XMLConstants::XSI_NS, type); - if (attribute) { - const XMLCh* attributeValue = attribute->getTextContent(); - if (attributeValue && *attributeValue) { - int i; - if ((i=XMLString::indexOf(attributeValue,chColon))>0) { - XMLCh* prefix=new XMLCh[i+1]; - XMLString::subString(prefix,attributeValue,0,i); - prefix[i]=chNull; - QName* ret=new QName(e->lookupNamespaceURI(prefix), attributeValue + i + 1, prefix); - delete[] prefix; - return ret; - } - else { - return new QName(e->lookupNamespaceURI(&chNull), attributeValue); - } - } - } - - return NULL; -} - -DOMAttr* XMLHelper::getIdAttribute(const DOMElement* domElement) -{ - if(!domElement->hasAttributes()) { - return NULL; - } - - DOMNamedNodeMap* attributes = domElement->getAttributes(); - DOMAttr* attribute; - for(XMLSize_t i = 0; i < attributes->getLength(); i++) { - attribute = static_cast(attributes->item(i)); - if(attribute->isId()) { - return attribute; - } - } - - return NULL; -} - -QName* XMLHelper::getNodeQName(const DOMNode* domNode) -{ - if (domNode) - return new QName(domNode->getNamespaceURI(), domNode->getLocalName(), domNode->getPrefix()); - return NULL; -} - -QName* XMLHelper::getAttributeValueAsQName(const DOMAttr* attribute) -{ - if (!attribute) - return NULL; - - int i; - const XMLCh* attributeValue=attribute->getTextContent(); - if (attributeValue && (i=XMLString::indexOf(attributeValue,chColon))>0) { - XMLCh* prefix=new XMLCh[i+1]; - XMLString::subString(prefix,attributeValue,0,i); - prefix[i]=chNull; - QName* ret=new QName(attribute->lookupNamespaceURI(prefix), attributeValue + i + 1, prefix); - delete[] prefix; - return ret; - } - - return new QName(attribute->lookupNamespaceURI(NULL), attributeValue); -} - -DOMElement* XMLHelper::appendChildElement(DOMElement* parentElement, DOMElement* childElement) -{ - DOMDocument* parentDocument = parentElement->getOwnerDocument(); - if (childElement->getOwnerDocument() != parentDocument) { - childElement = static_cast(parentDocument->importNode(childElement, true)); - } - - parentElement->appendChild(childElement); - return childElement; -} - -const XMLCh* XMLHelper::getTextContent(const DOMElement* e) -{ - DOMNode* child=e->getFirstChild(); - while (child) { - if (child->getNodeType()==DOMNode::TEXT_NODE) - return child->getNodeValue(); - child=child->getNextSibling(); - } - return NULL; -} - -DOMElement* XMLHelper::getFirstChildElement(const DOMNode* n, const XMLCh* localName) -{ - DOMNode* child = n->getFirstChild(); - while (child && child->getNodeType() != DOMNode::ELEMENT_NODE) - child = child->getNextSibling(); - if (child && localName) { - if (!XMLString::equals(localName,child->getLocalName())) - return getNextSiblingElement(child, localName); - } - return static_cast(child); -} - -DOMElement* XMLHelper::getLastChildElement(const DOMNode* n, const XMLCh* localName) -{ - DOMNode* child = n->getLastChild(); - while (child && child->getNodeType() != DOMNode::ELEMENT_NODE) - child = child->getPreviousSibling(); - if (child && localName) { - if (!XMLString::equals(localName,child->getLocalName())) - return getPreviousSiblingElement(child, localName); - } - return static_cast(child); -} - -DOMElement* XMLHelper::getFirstChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName) -{ - DOMElement* e = getFirstChildElement(n, localName); - while (e && !XMLString::equals(e->getNamespaceURI(),ns)) - e = getNextSiblingElement(e, localName); - return e; -} - -DOMElement* XMLHelper::getLastChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName) -{ - DOMElement* e = getLastChildElement(n, localName); - while (e && !XMLString::equals(e->getNamespaceURI(),ns)) - e = getPreviousSiblingElement(e, localName); - return e; -} - -DOMElement* XMLHelper::getNextSiblingElement(const DOMNode* n, const XMLCh* localName) -{ - DOMNode* sib = n->getNextSibling(); - while (sib && sib->getNodeType() != DOMNode::ELEMENT_NODE) - sib = sib->getNextSibling(); - if (sib && localName) { - if (!XMLString::equals(localName,sib->getLocalName())) - return getNextSiblingElement(sib, localName); - } - return static_cast(sib); -} - -DOMElement* XMLHelper::getPreviousSiblingElement(const DOMNode* n, const XMLCh* localName) -{ - DOMNode* sib = n->getPreviousSibling(); - while (sib && sib->getNodeType() != DOMNode::ELEMENT_NODE) - sib = sib->getPreviousSibling(); - if (sib && localName) { - if (!XMLString::equals(localName,sib->getLocalName())) - return getPreviousSiblingElement(sib, localName); - } - return static_cast(sib); -} - -DOMElement* XMLHelper::getNextSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName) -{ - DOMElement* e = getNextSiblingElement(n, localName); - while (e && !XMLString::equals(e->getNamespaceURI(),ns)) - e = getNextSiblingElement(e, localName); - return e; -} - -DOMElement* XMLHelper::getPreviousSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName) -{ - DOMElement* e = getPreviousSiblingElement(n, localName); - while (e && !XMLString::equals(e->getNamespaceURI(),ns)) - e = getPreviousSiblingElement(e, localName); - return e; -} - -void XMLHelper::serialize(const DOMElement* e, std::string& buf) -{ - static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull }; - static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDigit_8, chNull }; - DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(impltype); - DOMWriter* serializer=(static_cast(impl))->createDOMWriter(); - XercesJanitor janitor(serializer); - serializer->setEncoding(UTF8); - MemBufFormatTarget target; - if (!serializer->writeNode(&target,*e)) - throw XMLParserException("unable to serialize XML"); - buf.erase(); - buf.append(reinterpret_cast(target.getRawBuffer()),target.getLen()); -} +/* + * 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. + */ + +/** + * XMLHelper.cpp + * + * A helper class for working with W3C DOM objects. + */ + +#include "internal.h" +#include "exceptions.h" +#include "util/XMLHelper.h" +#include "util/XMLConstants.h" + +#include +#include + +using namespace xmltooling; + +static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull }; + +bool XMLHelper::hasXSIType(const DOMElement* e) +{ + if (e) { + if (e->hasAttributeNS(XMLConstants::XSI_NS, type)) { + return true; + } + } + + return false; +} + +QName* XMLHelper::getXSIType(const DOMElement* e) +{ + DOMAttr* attribute = e->getAttributeNodeNS(XMLConstants::XSI_NS, type); + if (attribute) { + const XMLCh* attributeValue = attribute->getTextContent(); + if (attributeValue && *attributeValue) { + int i; + if ((i=XMLString::indexOf(attributeValue,chColon))>0) { + XMLCh* prefix=new XMLCh[i+1]; + XMLString::subString(prefix,attributeValue,0,i); + prefix[i]=chNull; + QName* ret=new QName(e->lookupNamespaceURI(prefix), attributeValue + i + 1, prefix); + delete[] prefix; + return ret; + } + else { + return new QName(e->lookupNamespaceURI(&chNull), attributeValue); + } + } + } + + return NULL; +} + +DOMAttr* XMLHelper::getIdAttribute(const DOMElement* domElement) +{ + if(!domElement->hasAttributes()) { + return NULL; + } + + DOMNamedNodeMap* attributes = domElement->getAttributes(); + DOMAttr* attribute; + for(XMLSize_t i = 0; i < attributes->getLength(); i++) { + attribute = static_cast(attributes->item(i)); + if(attribute->isId()) { + return attribute; + } + } + + return NULL; +} + +QName* XMLHelper::getNodeQName(const DOMNode* domNode) +{ + if (domNode) + return new QName(domNode->getNamespaceURI(), domNode->getLocalName(), domNode->getPrefix()); + return NULL; +} + +QName* XMLHelper::getAttributeValueAsQName(const DOMAttr* attribute) +{ + if (!attribute) + return NULL; + + int i; + const XMLCh* attributeValue=attribute->getTextContent(); + if (attributeValue && (i=XMLString::indexOf(attributeValue,chColon))>0) { + XMLCh* prefix=new XMLCh[i+1]; + XMLString::subString(prefix,attributeValue,0,i); + prefix[i]=chNull; + QName* ret=new QName(attribute->lookupNamespaceURI(prefix), attributeValue + i + 1, prefix); + delete[] prefix; + return ret; + } + + return new QName(attribute->lookupNamespaceURI(NULL), attributeValue); +} + +DOMElement* XMLHelper::appendChildElement(DOMElement* parentElement, DOMElement* childElement) +{ + DOMDocument* parentDocument = parentElement->getOwnerDocument(); + if (childElement->getOwnerDocument() != parentDocument) { + childElement = static_cast(parentDocument->importNode(childElement, true)); + } + + parentElement->appendChild(childElement); + return childElement; +} + +const XMLCh* XMLHelper::getTextContent(const DOMElement* e) +{ + DOMNode* child=e->getFirstChild(); + while (child) { + if (child->getNodeType()==DOMNode::TEXT_NODE) + return child->getNodeValue(); + child=child->getNextSibling(); + } + return NULL; +} + +DOMElement* XMLHelper::getFirstChildElement(const DOMNode* n, const XMLCh* localName) +{ + DOMNode* child = n->getFirstChild(); + while (child && child->getNodeType() != DOMNode::ELEMENT_NODE) + child = child->getNextSibling(); + if (child && localName) { + if (!XMLString::equals(localName,child->getLocalName())) + return getNextSiblingElement(child, localName); + } + return static_cast(child); +} + +DOMElement* XMLHelper::getLastChildElement(const DOMNode* n, const XMLCh* localName) +{ + DOMNode* child = n->getLastChild(); + while (child && child->getNodeType() != DOMNode::ELEMENT_NODE) + child = child->getPreviousSibling(); + if (child && localName) { + if (!XMLString::equals(localName,child->getLocalName())) + return getPreviousSiblingElement(child, localName); + } + return static_cast(child); +} + +DOMElement* XMLHelper::getFirstChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName) +{ + DOMElement* e = getFirstChildElement(n, localName); + while (e && !XMLString::equals(e->getNamespaceURI(),ns)) + e = getNextSiblingElement(e, localName); + return e; +} + +DOMElement* XMLHelper::getLastChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName) +{ + DOMElement* e = getLastChildElement(n, localName); + while (e && !XMLString::equals(e->getNamespaceURI(),ns)) + e = getPreviousSiblingElement(e, localName); + return e; +} + +DOMElement* XMLHelper::getNextSiblingElement(const DOMNode* n, const XMLCh* localName) +{ + DOMNode* sib = n->getNextSibling(); + while (sib && sib->getNodeType() != DOMNode::ELEMENT_NODE) + sib = sib->getNextSibling(); + if (sib && localName) { + if (!XMLString::equals(localName,sib->getLocalName())) + return getNextSiblingElement(sib, localName); + } + return static_cast(sib); +} + +DOMElement* XMLHelper::getPreviousSiblingElement(const DOMNode* n, const XMLCh* localName) +{ + DOMNode* sib = n->getPreviousSibling(); + while (sib && sib->getNodeType() != DOMNode::ELEMENT_NODE) + sib = sib->getPreviousSibling(); + if (sib && localName) { + if (!XMLString::equals(localName,sib->getLocalName())) + return getPreviousSiblingElement(sib, localName); + } + return static_cast(sib); +} + +DOMElement* XMLHelper::getNextSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName) +{ + DOMElement* e = getNextSiblingElement(n, localName); + while (e && !XMLString::equals(e->getNamespaceURI(),ns)) + e = getNextSiblingElement(e, localName); + return e; +} + +DOMElement* XMLHelper::getPreviousSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName) +{ + DOMElement* e = getPreviousSiblingElement(n, localName); + while (e && !XMLString::equals(e->getNamespaceURI(),ns)) + e = getPreviousSiblingElement(e, localName); + return e; +} + +void XMLHelper::serialize(const DOMElement* e, std::string& buf) +{ + static const XMLCh impltype[] = { chLatin_L, chLatin_S, chNull }; + static const XMLCh UTF8[]={ chLatin_U, chLatin_T, chLatin_F, chDigit_8, chNull }; + DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(impltype); + DOMWriter* serializer=(static_cast(impl))->createDOMWriter(); + XercesJanitor janitor(serializer); + serializer->setEncoding(UTF8); + MemBufFormatTarget target; + if (!serializer->writeNode(&target,*e)) + throw XMLParserException("unable to serialize XML"); + buf.erase(); + buf.append(reinterpret_cast(target.getRawBuffer()),target.getLen()); +} diff --git a/xmltooling/util/XMLHelper.h b/xmltooling/util/XMLHelper.h index df33c63..868d00f 100644 --- a/xmltooling/util/XMLHelper.h +++ b/xmltooling/util/XMLHelper.h @@ -1,226 +1,226 @@ -/* - * 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 XMLHelper.h - * - * A helper class for working with W3C DOM objects. - */ - -#ifndef __xmltooling_xmlhelper_h__ -#define __xmltooling_xmlhelper_h__ - -#include -#include - -using namespace xercesc; - -namespace xmltooling { - - /** - * RAII wrapper for Xerces resources. - */ - template class XercesJanitor - { - MAKE_NONCOPYABLE(XercesJanitor); - T* m_held; - public: - XercesJanitor(T* resource) : m_held(resource) {} - - ~XercesJanitor() { - if (m_held) - m_held->release(); - } - - /** - * Returns resource held by this object and releases it to the caller. - * - * @return the resource held or NULL - */ - T* release() { - T* ret=m_held; - m_held=NULL; - return ret; - } - }; - - /** - * A helper class for working with W3C DOM objects. - */ - class XMLTOOL_API XMLHelper - { - public: - /** - * Checks if the given element has an xsi:type defined for it - * - * @param e the DOM element - * @return true if there is a type, false if not - */ - static bool hasXSIType(const DOMElement* e); - - /** - * Gets the XSI type for a given element if it has one. - * - * @param e the element - * @return the type or null - */ - static QName* getXSIType(const DOMElement* e); - - /** - * Gets the ID attribute of a DOM element. - * - * @param domElement the DOM element - * @return the ID attribute or null if there isn't one - */ - static DOMAttr* getIdAttribute(const DOMElement* domElement); - - /** - * Gets the QName for the given DOM node. - * - * @param domNode the DOM node - * @return the QName for the element or null if the element was null - */ - static QName* getNodeQName(const DOMNode* domNode); - - /** - * Constructs a QName from an attribute's value. - * - * @param attribute the attribute with a QName value - * @return a QName from an attribute's value, or null if the given attribute is null - */ - static QName* getAttributeValueAsQName(const DOMAttr* attribute); - - /** - * Appends the child Element to the parent Element, - * importing the child Element into the parent's Document if needed. - * - * @param parentElement the parent Element - * @param childElement the child Element - * @return the child Element that was added (may be an imported copy) - */ - static DOMElement* appendChildElement(DOMElement* parentElement, DOMElement* childElement); - - /** - * Checks the qualified name of a node. - * - * @param n node to check - * @param ns namespace to compare with - * @param local local name to compare with - * @return true iff the node's qualified name matches the other parameters - */ - static bool isNodeNamed(const DOMNode* n, const XMLCh* ns, const XMLCh* local) { - return (n && XMLString::equals(local,n->getLocalName()) && XMLString::equals(ns,n->getNamespaceURI())); - } - - /** - * Returns the first matching child element of the node if any. - * - * @param n node to check - * @param localName local name to compare with or NULL for any match - * @return the first matching child node of type Element, or NULL - */ - static DOMElement* getFirstChildElement(const DOMNode* n, const XMLCh* localName=NULL); - - /** - * Returns the last matching child element of the node if any. - * - * @param n node to check - * @param localName local name to compare with or NULL for any match - * @return the last matching child node of type Element, or NULL - */ - static DOMElement* getLastChildElement(const DOMNode* n, const XMLCh* localName=NULL); - - /** - * Returns the next matching sibling element of the node if any. - * - * @param n node to check - * @param localName local name to compare with or NULL for any match - * @return the next matching sibling node of type Element, or NULL - */ - static DOMElement* getNextSiblingElement(const DOMNode* n, const XMLCh* localName=NULL); - - /** - * Returns the previous matching sibling element of the node if any. - * - * @param n node to check - * @param localName local name to compare with or NULL for any match - * @return the previous matching sibling node of type Element, or NULL - */ - static DOMElement* getPreviousSiblingElement(const DOMNode* n, const XMLCh* localName=NULL); - - /** - * Returns the first matching child element of the node if any. - * - * @param n node to check - * @param ns namespace to compare with - * @param localName local name to compare with - * @return the first matching child node of type Element, or NULL - */ - static DOMElement* getFirstChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName); - - /** - * Returns the last matching child element of the node if any. - * - * @param n node to check - * @param ns namespace to compare with - * @param localName local name to compare with - * @return the last matching child node of type Element, or NULL - */ - static DOMElement* getLastChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName); - - /** - * Returns the next matching sibling element of the node if any. - * - * @param n node to check - * @param ns namespace to compare with - * @param localName local name to compare with - * @return the next matching sibling node of type Element, or NULL - */ - static DOMElement* getNextSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName); - - /** - * Returns the previous matching sibling element of the node if any. - * - * @param n node to check - * @param ns namespace to compare with - * @param localName local name to compare with - * @return the previous matching sibling node of type Element, or NULL - */ - static DOMElement* getPreviousSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName); - - /** - * Returns the content of the first Text node found in the element, if any. - * This is roughly similar to the DOM getTextContent function, but only - * examples the immediate children of the element. - * - * @param e element to examine - * @return the content of the first Text node found, or NULL - */ - static const XMLCh* getTextContent(const DOMElement* e); - - /** - * Serializes the DOM Element provided into a buffer using UTF-8 encoding and - * the default XML serializer available. No manipulation or formatting is applied. - * - * @param e element to serialize - * @param buf buffer to serialize element into - */ - static void serialize(const DOMElement* e, std::string& buf); - }; - -}; - -#endif /* __xmltooling_xmlhelper_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 XMLHelper.h + * + * A helper class for working with W3C DOM objects. + */ + +#ifndef __xmltooling_xmlhelper_h__ +#define __xmltooling_xmlhelper_h__ + +#include +#include + +using namespace xercesc; + +namespace xmltooling { + + /** + * RAII wrapper for Xerces resources. + */ + template class XercesJanitor + { + MAKE_NONCOPYABLE(XercesJanitor); + T* m_held; + public: + XercesJanitor(T* resource) : m_held(resource) {} + + ~XercesJanitor() { + if (m_held) + m_held->release(); + } + + /** + * Returns resource held by this object and releases it to the caller. + * + * @return the resource held or NULL + */ + T* release() { + T* ret=m_held; + m_held=NULL; + return ret; + } + }; + + /** + * A helper class for working with W3C DOM objects. + */ + class XMLTOOL_API XMLHelper + { + public: + /** + * Checks if the given element has an xsi:type defined for it + * + * @param e the DOM element + * @return true if there is a type, false if not + */ + static bool hasXSIType(const DOMElement* e); + + /** + * Gets the XSI type for a given element if it has one. + * + * @param e the element + * @return the type or null + */ + static QName* getXSIType(const DOMElement* e); + + /** + * Gets the ID attribute of a DOM element. + * + * @param domElement the DOM element + * @return the ID attribute or null if there isn't one + */ + static DOMAttr* getIdAttribute(const DOMElement* domElement); + + /** + * Gets the QName for the given DOM node. + * + * @param domNode the DOM node + * @return the QName for the element or null if the element was null + */ + static QName* getNodeQName(const DOMNode* domNode); + + /** + * Constructs a QName from an attribute's value. + * + * @param attribute the attribute with a QName value + * @return a QName from an attribute's value, or null if the given attribute is null + */ + static QName* getAttributeValueAsQName(const DOMAttr* attribute); + + /** + * Appends the child Element to the parent Element, + * importing the child Element into the parent's Document if needed. + * + * @param parentElement the parent Element + * @param childElement the child Element + * @return the child Element that was added (may be an imported copy) + */ + static DOMElement* appendChildElement(DOMElement* parentElement, DOMElement* childElement); + + /** + * Checks the qualified name of a node. + * + * @param n node to check + * @param ns namespace to compare with + * @param local local name to compare with + * @return true iff the node's qualified name matches the other parameters + */ + static bool isNodeNamed(const DOMNode* n, const XMLCh* ns, const XMLCh* local) { + return (n && XMLString::equals(local,n->getLocalName()) && XMLString::equals(ns,n->getNamespaceURI())); + } + + /** + * Returns the first matching child element of the node if any. + * + * @param n node to check + * @param localName local name to compare with or NULL for any match + * @return the first matching child node of type Element, or NULL + */ + static DOMElement* getFirstChildElement(const DOMNode* n, const XMLCh* localName=NULL); + + /** + * Returns the last matching child element of the node if any. + * + * @param n node to check + * @param localName local name to compare with or NULL for any match + * @return the last matching child node of type Element, or NULL + */ + static DOMElement* getLastChildElement(const DOMNode* n, const XMLCh* localName=NULL); + + /** + * Returns the next matching sibling element of the node if any. + * + * @param n node to check + * @param localName local name to compare with or NULL for any match + * @return the next matching sibling node of type Element, or NULL + */ + static DOMElement* getNextSiblingElement(const DOMNode* n, const XMLCh* localName=NULL); + + /** + * Returns the previous matching sibling element of the node if any. + * + * @param n node to check + * @param localName local name to compare with or NULL for any match + * @return the previous matching sibling node of type Element, or NULL + */ + static DOMElement* getPreviousSiblingElement(const DOMNode* n, const XMLCh* localName=NULL); + + /** + * Returns the first matching child element of the node if any. + * + * @param n node to check + * @param ns namespace to compare with + * @param localName local name to compare with + * @return the first matching child node of type Element, or NULL + */ + static DOMElement* getFirstChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName); + + /** + * Returns the last matching child element of the node if any. + * + * @param n node to check + * @param ns namespace to compare with + * @param localName local name to compare with + * @return the last matching child node of type Element, or NULL + */ + static DOMElement* getLastChildElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName); + + /** + * Returns the next matching sibling element of the node if any. + * + * @param n node to check + * @param ns namespace to compare with + * @param localName local name to compare with + * @return the next matching sibling node of type Element, or NULL + */ + static DOMElement* getNextSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName); + + /** + * Returns the previous matching sibling element of the node if any. + * + * @param n node to check + * @param ns namespace to compare with + * @param localName local name to compare with + * @return the previous matching sibling node of type Element, or NULL + */ + static DOMElement* getPreviousSiblingElement(const DOMNode* n, const XMLCh* ns, const XMLCh* localName); + + /** + * Returns the content of the first Text node found in the element, if any. + * This is roughly similar to the DOM getTextContent function, but only + * examples the immediate children of the element. + * + * @param e element to examine + * @return the content of the first Text node found, or NULL + */ + static const XMLCh* getTextContent(const DOMElement* e); + + /** + * Serializes the DOM Element provided into a buffer using UTF-8 encoding and + * the default XML serializer available. No manipulation or formatting is applied. + * + * @param e element to serialize + * @param buf buffer to serialize element into + */ + static void serialize(const DOMElement* e, std::string& buf); + }; + +}; + +#endif /* __xmltooling_xmlhelper_h__ */ diff --git a/xmltooling/validation/Validator.h b/xmltooling/validation/Validator.h index 58256bf..b56f6a7 100644 --- a/xmltooling/validation/Validator.h +++ b/xmltooling/validation/Validator.h @@ -1,55 +1,55 @@ -/* - * 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 Validator.h - * - * Rules checking of XMLObjects - */ - -#ifndef __xmltooling_validator_h__ -#define __xmltooling_validator_h__ - -#include - -namespace xmltooling { - - /** - * An interface for classes that implement rules for checking the - * validity of XMLObjects. - */ - class XMLTOOL_API Validator - { - MAKE_NONCOPYABLE(Validator); - public: - virtual ~Validator() {} - - /** - * Checks to see if an XMLObject is valid. - * - * @param xmlObject the XMLObject to validate - - * @throws ValidationException thrown if the element is not valid - */ - virtual void validate(const XMLObject* xmlObject) const=0; - - protected: - Validator() {} - }; - -}; - -#endif /* __xmltooling_validator_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 Validator.h + * + * Rules checking of XMLObjects + */ + +#ifndef __xmltooling_validator_h__ +#define __xmltooling_validator_h__ + +#include + +namespace xmltooling { + + /** + * An interface for classes that implement rules for checking the + * validity of XMLObjects. + */ + class XMLTOOL_API Validator + { + MAKE_NONCOPYABLE(Validator); + public: + virtual ~Validator() {} + + /** + * Checks to see if an XMLObject is valid. + * + * @param xmlObject the XMLObject to validate + + * @throws ValidationException thrown if the element is not valid + */ + virtual void validate(const XMLObject* xmlObject) const=0; + + protected: + Validator() {} + }; + +}; + +#endif /* __xmltooling_validator_h__ */ diff --git a/xmltooling/validation/ValidatorSuite.cpp b/xmltooling/validation/ValidatorSuite.cpp index 742e4bd..1fb65d9 100644 --- a/xmltooling/validation/ValidatorSuite.cpp +++ b/xmltooling/validation/ValidatorSuite.cpp @@ -1,67 +1,67 @@ -/* - * 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. - */ - -/** - * ValidatorSuite.cpp - * - * Groups of rule checkers of XMLObjects based on type or element name. - */ - -#include "internal.h" -#include "validation/ValidatorSuite.h" -#include "util/XMLHelper.h" - -using namespace xmltooling; -using namespace std; - -ValidatorSuite xmltooling::SchemaValidators("SchemaValidators"); - -void ValidatorSuite::deregisterValidators(const QName& key) -{ - pair::iterator,multimap::iterator> range=m_map.equal_range(key); - for_each(range.first, range.second, xmltooling::cleanup_pair()); - m_map.erase(range.first, range.second); -} - -void ValidatorSuite::destroyValidators() -{ - for_each(m_map.begin(),m_map.end(),xmltooling::cleanup_pair()); - m_map.clear(); -} - -void ValidatorSuite::validate(const XMLObject* xmlObject) const -{ - if (!xmlObject) - return; - - pair::const_iterator,multimap::const_iterator> range; - if (xmlObject->getSchemaType()) { - range=m_map.equal_range(*(xmlObject->getSchemaType())); - while (range.first!=range.second) { - range.first->second->validate(xmlObject); - ++range.first; - } - } - range=m_map.equal_range(xmlObject->getElementQName()); - while (range.first!=range.second) { - range.first->second->validate(xmlObject); - ++range.first; - } - - const list& kids=xmlObject->getOrderedChildren(); - for (list::const_iterator j=kids.begin(); j!=kids.end(); j++) - validate(*j); -} +/* + * 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. + */ + +/** + * ValidatorSuite.cpp + * + * Groups of rule checkers of XMLObjects based on type or element name. + */ + +#include "internal.h" +#include "validation/ValidatorSuite.h" +#include "util/XMLHelper.h" + +using namespace xmltooling; +using namespace std; + +ValidatorSuite xmltooling::SchemaValidators("SchemaValidators"); + +void ValidatorSuite::deregisterValidators(const QName& key) +{ + pair::iterator,multimap::iterator> range=m_map.equal_range(key); + for_each(range.first, range.second, xmltooling::cleanup_pair()); + m_map.erase(range.first, range.second); +} + +void ValidatorSuite::destroyValidators() +{ + for_each(m_map.begin(),m_map.end(),xmltooling::cleanup_pair()); + m_map.clear(); +} + +void ValidatorSuite::validate(const XMLObject* xmlObject) const +{ + if (!xmlObject) + return; + + pair::const_iterator,multimap::const_iterator> range; + if (xmlObject->getSchemaType()) { + range=m_map.equal_range(*(xmlObject->getSchemaType())); + while (range.first!=range.second) { + range.first->second->validate(xmlObject); + ++range.first; + } + } + range=m_map.equal_range(xmlObject->getElementQName()); + while (range.first!=range.second) { + range.first->second->validate(xmlObject); + ++range.first; + } + + const list& kids=xmlObject->getOrderedChildren(); + for (list::const_iterator j=kids.begin(); j!=kids.end(); j++) + validate(*j); +} diff --git a/xmltooling/validation/ValidatorSuite.h b/xmltooling/validation/ValidatorSuite.h index cea0693..9fc63a6 100644 --- a/xmltooling/validation/ValidatorSuite.h +++ b/xmltooling/validation/ValidatorSuite.h @@ -1,120 +1,120 @@ -/* - * 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 ValidatorSuite.h - * - * Groups of rule checkers of XMLObjects based on type or element name. - */ - -#ifndef __xmltooling_valsuite_h__ -#define __xmltooling_valsuite_h__ - -#include -#include - -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * A collection of validators that can be applied to an XMLObject and its children. These collections can represent - * usage specific checks, such as those outlined in schemas or profiles of specific XML specifications. - * - * Registered Validators must be stateless. Validators are fetched based on schema type and - * element name, in that order. - */ - class XMLTOOL_API ValidatorSuite - { - MAKE_NONCOPYABLE(ValidatorSuite); - public: - /** - * Creates a new suite. - * - * @param id an identifier for the suite - */ - ValidatorSuite(const char* id) : m_id(id) {} - - ~ValidatorSuite() { - destroyValidators(); - } - - /** - * Gets a unique ID for this suite. - * - * @return a unique ID for this suite - */ - const char* getId() { - return m_id.c_str(); - } - - /** - * Evaluates the registered validators against the given XMLObject and it's children. - * - * @param xmlObject the XMLObject tree to validate - * - * @throws ValidationException thrown if the element tree is not valid - */ - void validate(const XMLObject* xmlObject) const; - - /** - * Registers a new validator for the given key. - * - * @param key the key used to retrieve the validator - * @param validator the validator - */ - void registerValidator(const QName& key, Validator* validator) { - m_map.insert(std::make_pair(key,validator)); - } - - /** - * Deregisters validators. - * - * @param key the key for the validators to be deregistered - */ - void deregisterValidators(const QName& key); - - /** - * Unregisters and destroys all registered validators. - */ - void destroyValidators(); - - private: - std::string m_id; - std::multimap m_map; - }; - - /** - * Validator suite for schema-style structural validation. - * - * This is NOT a comprehensive replacement for real - * schema validation, but it does basic structural checking of overall - * element relationships and some basic attribute presence checking. - */ - extern XMLTOOL_API xmltooling::ValidatorSuite SchemaValidators; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_valsuite_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 ValidatorSuite.h + * + * Groups of rule checkers of XMLObjects based on type or element name. + */ + +#ifndef __xmltooling_valsuite_h__ +#define __xmltooling_valsuite_h__ + +#include +#include + +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * A collection of validators that can be applied to an XMLObject and its children. These collections can represent + * usage specific checks, such as those outlined in schemas or profiles of specific XML specifications. + * + * Registered Validators must be stateless. Validators are fetched based on schema type and + * element name, in that order. + */ + class XMLTOOL_API ValidatorSuite + { + MAKE_NONCOPYABLE(ValidatorSuite); + public: + /** + * Creates a new suite. + * + * @param id an identifier for the suite + */ + ValidatorSuite(const char* id) : m_id(id) {} + + ~ValidatorSuite() { + destroyValidators(); + } + + /** + * Gets a unique ID for this suite. + * + * @return a unique ID for this suite + */ + const char* getId() { + return m_id.c_str(); + } + + /** + * Evaluates the registered validators against the given XMLObject and it's children. + * + * @param xmlObject the XMLObject tree to validate + * + * @throws ValidationException thrown if the element tree is not valid + */ + void validate(const XMLObject* xmlObject) const; + + /** + * Registers a new validator for the given key. + * + * @param key the key used to retrieve the validator + * @param validator the validator + */ + void registerValidator(const QName& key, Validator* validator) { + m_map.insert(std::make_pair(key,validator)); + } + + /** + * Deregisters validators. + * + * @param key the key for the validators to be deregistered + */ + void deregisterValidators(const QName& key); + + /** + * Unregisters and destroys all registered validators. + */ + void destroyValidators(); + + private: + std::string m_id; + std::multimap m_map; + }; + + /** + * Validator suite for schema-style structural validation. + * + * This is NOT a comprehensive replacement for real + * schema validation, but it does basic structural checking of overall + * element relationships and some basic attribute presence checking. + */ + extern XMLTOOL_API xmltooling::ValidatorSuite SchemaValidators; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_valsuite_h__ */ diff --git a/xmltooling/version.h b/xmltooling/version.h index 21bc63b..a399a24 100644 --- a/xmltooling/version.h +++ b/xmltooling/version.h @@ -1,74 +1,74 @@ -/* - * 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. - */ - -/** - * version.h - * - * Library version macros and constants - */ - -#if !defined(__xmltooling_version_h__) -#define __xmltooling_version_h__ - -// This is all based on Xerces, on the theory it might be useful to -// support this kind of stuff in the future. If they ever yank some -// of this stuff, it can be copied into here. - -#include - -// --------------------------------------------------------------------------- -// V E R S I O N S P E C I F I C A T I O N - -/** - * MODIFY THESE NUMERIC VALUES TO COINCIDE WITH XMLTOOLING VERSION - * AND DO NOT MODIFY ANYTHING ELSE IN THIS VERSION HEADER FILE - */ - -#define XMLTOOLING_VERSION_MAJOR 1 -#define XMLTOOLING_VERSION_MINOR 0 -#define XMLTOOLING_VERSION_REVISION 0 - -/** DO NOT MODIFY BELOW THIS LINE */ - -/** - * MAGIC THAT AUTOMATICALLY GENERATES THE FOLLOWING: - * - * gXMLToolingVersionStr, gXMLToolingFullVersionStr, gXMLToolingMajVersion, gXMLToolingMinVersion, gXMLToolingRevision - */ - -// --------------------------------------------------------------------------- -// V E R S I O N I N F O R M A T I O N - -// XMLTooling version strings; these particular macros cannot be used for -// conditional compilation as they are not numeric constants - -#define XMLTOOLING_FULLVERSIONSTR INVK_CAT3_SEP_UNDERSCORE(XMLTOOLING_VERSION_MAJOR,XMLTOOLING_VERSION_MINOR,XMLTOOLING_VERSION_REVISION) -#define XMLTOOLING_FULLVERSIONDOT INVK_CAT3_SEP_PERIOD(XMLTOOLING_VERSION_MAJOR,XMLTOOLING_VERSION_MINOR,XMLTOOLING_VERSION_REVISION) -#define XMLTOOLING_FULLVERSIONNUM INVK_CAT3_SEP_NIL(XMLTOOLING_VERSION_MAJOR,XMLTOOLING_VERSION_MINOR,XMLTOOLING_VERSION_REVISION) -#define XMLTOOLING_VERSIONSTR INVK_CAT2_SEP_UNDERSCORE(XMLTOOLING_VERSION_MAJOR,XMLTOOLING_VERSION_MINOR) - -const char* const gXMLToolingVersionStr = XMLTOOLING_VERSIONSTR; -const char* const gXMLToolingFullVersionStr = XMLTOOLING_FULLVERSIONSTR; -const unsigned int gXMLToolingMajVersion = XMLTOOLING_VERSION_MAJOR; -const unsigned int gXMLToolingMinVersion = XMLTOOLING_VERSION_MINOR; -const unsigned int gXMLToolingRevision = XMLTOOLING_VERSION_REVISION; - -// XMLTooling version numeric constants that can be used for conditional -// compilation purposes. - -#define _XMLTOOLING_VERSION CALC_EXPANDED_FORM (XMLTOOLING_VERSION_MAJOR,XMLTOOLING_VERSION_MINOR,XMLTOOLING_VERSION_REVISION) - -#endif // __xmltooling_version_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. + */ + +/** + * version.h + * + * Library version macros and constants + */ + +#if !defined(__xmltooling_version_h__) +#define __xmltooling_version_h__ + +// This is all based on Xerces, on the theory it might be useful to +// support this kind of stuff in the future. If they ever yank some +// of this stuff, it can be copied into here. + +#include + +// --------------------------------------------------------------------------- +// V E R S I O N S P E C I F I C A T I O N + +/** + * MODIFY THESE NUMERIC VALUES TO COINCIDE WITH XMLTOOLING VERSION + * AND DO NOT MODIFY ANYTHING ELSE IN THIS VERSION HEADER FILE + */ + +#define XMLTOOLING_VERSION_MAJOR 1 +#define XMLTOOLING_VERSION_MINOR 0 +#define XMLTOOLING_VERSION_REVISION 0 + +/** DO NOT MODIFY BELOW THIS LINE */ + +/** + * MAGIC THAT AUTOMATICALLY GENERATES THE FOLLOWING: + * + * gXMLToolingVersionStr, gXMLToolingFullVersionStr, gXMLToolingMajVersion, gXMLToolingMinVersion, gXMLToolingRevision + */ + +// --------------------------------------------------------------------------- +// V E R S I O N I N F O R M A T I O N + +// XMLTooling version strings; these particular macros cannot be used for +// conditional compilation as they are not numeric constants + +#define XMLTOOLING_FULLVERSIONSTR INVK_CAT3_SEP_UNDERSCORE(XMLTOOLING_VERSION_MAJOR,XMLTOOLING_VERSION_MINOR,XMLTOOLING_VERSION_REVISION) +#define XMLTOOLING_FULLVERSIONDOT INVK_CAT3_SEP_PERIOD(XMLTOOLING_VERSION_MAJOR,XMLTOOLING_VERSION_MINOR,XMLTOOLING_VERSION_REVISION) +#define XMLTOOLING_FULLVERSIONNUM INVK_CAT3_SEP_NIL(XMLTOOLING_VERSION_MAJOR,XMLTOOLING_VERSION_MINOR,XMLTOOLING_VERSION_REVISION) +#define XMLTOOLING_VERSIONSTR INVK_CAT2_SEP_UNDERSCORE(XMLTOOLING_VERSION_MAJOR,XMLTOOLING_VERSION_MINOR) + +const char* const gXMLToolingVersionStr = XMLTOOLING_VERSIONSTR; +const char* const gXMLToolingFullVersionStr = XMLTOOLING_FULLVERSIONSTR; +const unsigned int gXMLToolingMajVersion = XMLTOOLING_VERSION_MAJOR; +const unsigned int gXMLToolingMinVersion = XMLTOOLING_VERSION_MINOR; +const unsigned int gXMLToolingRevision = XMLTOOLING_VERSION_REVISION; + +// XMLTooling version numeric constants that can be used for conditional +// compilation purposes. + +#define _XMLTOOLING_VERSION CALC_EXPANDED_FORM (XMLTOOLING_VERSION_MAJOR,XMLTOOLING_VERSION_MINOR,XMLTOOLING_VERSION_REVISION) + +#endif // __xmltooling_version_h__ diff --git a/xmltoolingtest/ComplexXMLObjectTest.h b/xmltoolingtest/ComplexXMLObjectTest.h index 908e4d4..0633ada 100644 --- a/xmltoolingtest/ComplexXMLObjectTest.h +++ b/xmltoolingtest/ComplexXMLObjectTest.h @@ -1,69 +1,69 @@ -/* - * Copyright 2001-2005 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. - */ - -#include "XMLObjectBaseTestCase.h" - -#include -#include - -class ComplexXMLObjectTest : public CxxTest::TestSuite { -public: - ComplexXMLObjectTest() {} - - void setUp() { - XMLObjectBuilder::registerDefaultBuilder(new AnyElementBuilder()); - } - - void tearDown() { - XMLObjectBuilder::deregisterDefaultBuilder(); - } - - void testComplexUnmarshalling() { - string path=data_path + "ComplexXMLObject.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - XercesJanitor janitor(doc); - - const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - - auto_ptr wcObject( - dynamic_cast(b->buildFromDocument(doc, false)) - ); - TS_ASSERT(wcObject.get()!=NULL); - - ListOf(XMLObject) kids=wcObject->getXMLObjects(); - TSM_ASSERT_EQUALS("Number of child elements was not expected value", 2, kids.size()); - - ElementProxy* wc1=dynamic_cast(*(++kids.begin())); - ElementProxy* wc2=dynamic_cast(*(++(wc1->getXMLObjects().begin()))); - TSM_ASSERT_EQUALS("Number of child elements was not expected value", 3, wc2->getXMLObjects().size()); - - static const XMLCh html[] = {chLatin_h, chLatin_t, chLatin_m, chLatin_l, chNull}; - static const XMLCh div[] = {chLatin_d, chLatin_i, chLatin_v, chNull}; - auto_ptr_XMLCh htmlns("http://www.w3.org/1999/xhtml"); - QName q(htmlns.get(),div,html); - ListOf(XMLObject)::const_iterator it=wc2->getXMLObjects().begin(); - ++it; ++it; - TSM_ASSERT_EQUALS("Element QName unexpected", it->getElementQName(),q); - - DOMElement* rebuilt = wcObject->marshall(XMLToolingConfig::getConfig().getParser().newDocument()); - wcObject->setDocument(rebuilt->getOwnerDocument()); - TS_ASSERT(rebuilt->isEqualNode(doc->getDocumentElement())); - } - -}; +/* + * Copyright 2001-2005 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include +#include + +class ComplexXMLObjectTest : public CxxTest::TestSuite { +public: + ComplexXMLObjectTest() {} + + void setUp() { + XMLObjectBuilder::registerDefaultBuilder(new AnyElementBuilder()); + } + + void tearDown() { + XMLObjectBuilder::deregisterDefaultBuilder(); + } + + void testComplexUnmarshalling() { + string path=data_path + "ComplexXMLObject.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + XercesJanitor janitor(doc); + + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr wcObject( + dynamic_cast(b->buildFromDocument(doc, false)) + ); + TS_ASSERT(wcObject.get()!=NULL); + + ListOf(XMLObject) kids=wcObject->getXMLObjects(); + TSM_ASSERT_EQUALS("Number of child elements was not expected value", 2, kids.size()); + + ElementProxy* wc1=dynamic_cast(*(++kids.begin())); + ElementProxy* wc2=dynamic_cast(*(++(wc1->getXMLObjects().begin()))); + TSM_ASSERT_EQUALS("Number of child elements was not expected value", 3, wc2->getXMLObjects().size()); + + static const XMLCh html[] = {chLatin_h, chLatin_t, chLatin_m, chLatin_l, chNull}; + static const XMLCh div[] = {chLatin_d, chLatin_i, chLatin_v, chNull}; + auto_ptr_XMLCh htmlns("http://www.w3.org/1999/xhtml"); + QName q(htmlns.get(),div,html); + ListOf(XMLObject)::const_iterator it=wc2->getXMLObjects().begin(); + ++it; ++it; + TSM_ASSERT_EQUALS("Element QName unexpected", it->getElementQName(),q); + + DOMElement* rebuilt = wcObject->marshall(XMLToolingConfig::getConfig().getParser().newDocument()); + wcObject->setDocument(rebuilt->getOwnerDocument()); + TS_ASSERT(rebuilt->isEqualNode(doc->getDocumentElement())); + } + +}; diff --git a/xmltoolingtest/EncryptionTest.h b/xmltoolingtest/EncryptionTest.h index 3f88890..8f9e4c7 100644 --- a/xmltoolingtest/EncryptionTest.h +++ b/xmltoolingtest/EncryptionTest.h @@ -1,93 +1,93 @@ -/* - * Copyright 2001-2005 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. - */ - -#include "XMLObjectBaseTestCase.h" - -#include -#include -#include - -#include -#include -#include - -using namespace xmlencryption; - -class _addcert : public std::binary_function { -public: - void operator()(X509Data* bag, XSECCryptoX509* cert) const { - safeBuffer& buf=cert->getDEREncodingSB(); - X509Certificate* x=X509CertificateBuilder::buildX509Certificate(); - x->setValue(buf.sbStrToXMLCh()); - bag->getX509Certificates().push_back(x); - } -}; - -class EncryptionTest : public CxxTest::TestSuite { - CredentialResolver* m_resolver; -public: - void setUp() { - m_resolver=NULL; - string config = data_path + "FilesystemCredentialResolver.xml"; - ifstream in(config.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); - XercesJanitor janitor(doc); - m_resolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin( - FILESYSTEM_CREDENTIAL_RESOLVER,doc->getDocumentElement() - ); - } - - void tearDown() { - delete m_resolver; - } - - void testEncryption() { - string path=data_path + "ComplexXMLObject.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - try { - Locker locker(m_resolver); - Encrypter encrypter; - Encrypter::EncryptionParams ep; - Encrypter::KeyEncryptionParams kep(DSIGConstants::s_unicodeStrURIRSA_1_5,m_resolver->getKey()); - auto_ptr encData(encrypter.encryptElement(doc->getDocumentElement(),ep,&kep)); - - string buf; - XMLHelper::serialize(encData->marshall(), buf); - istringstream is(buf); - DOMDocument* doc2=XMLToolingConfig::getConfig().getValidatingParser().parse(is); - auto_ptr encData2( - dynamic_cast(XMLObjectBuilder::buildOneFromElement(doc2->getDocumentElement(),true)) - ); - - Decrypter decrypter(new KeyResolver(m_resolver->getKey())); - DOMDocumentFragment* frag = decrypter.decryptData(encData2.get()); - XMLHelper::serialize(static_cast(frag->getFirstChild()), buf); - //TS_TRACE(buf.c_str()); - TS_ASSERT(doc->getDocumentElement()->isEqualNode(frag->getFirstChild())); - frag->release(); - doc->release(); - } - catch (XMLToolingException& e) { - TS_TRACE(e.what()); - doc->release(); - throw; - } - } - -}; +/* + * Copyright 2001-2005 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include +#include +#include + +#include +#include +#include + +using namespace xmlencryption; + +class _addcert : public std::binary_function { +public: + void operator()(X509Data* bag, XSECCryptoX509* cert) const { + safeBuffer& buf=cert->getDEREncodingSB(); + X509Certificate* x=X509CertificateBuilder::buildX509Certificate(); + x->setValue(buf.sbStrToXMLCh()); + bag->getX509Certificates().push_back(x); + } +}; + +class EncryptionTest : public CxxTest::TestSuite { + CredentialResolver* m_resolver; +public: + void setUp() { + m_resolver=NULL; + string config = data_path + "FilesystemCredentialResolver.xml"; + ifstream in(config.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); + XercesJanitor janitor(doc); + m_resolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin( + FILESYSTEM_CREDENTIAL_RESOLVER,doc->getDocumentElement() + ); + } + + void tearDown() { + delete m_resolver; + } + + void testEncryption() { + string path=data_path + "ComplexXMLObject.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + try { + Locker locker(m_resolver); + Encrypter encrypter; + Encrypter::EncryptionParams ep; + Encrypter::KeyEncryptionParams kep(DSIGConstants::s_unicodeStrURIRSA_1_5,m_resolver->getKey()); + auto_ptr encData(encrypter.encryptElement(doc->getDocumentElement(),ep,&kep)); + + string buf; + XMLHelper::serialize(encData->marshall(), buf); + istringstream is(buf); + DOMDocument* doc2=XMLToolingConfig::getConfig().getValidatingParser().parse(is); + auto_ptr encData2( + dynamic_cast(XMLObjectBuilder::buildOneFromElement(doc2->getDocumentElement(),true)) + ); + + Decrypter decrypter(new KeyResolver(m_resolver->getKey())); + DOMDocumentFragment* frag = decrypter.decryptData(encData2.get()); + XMLHelper::serialize(static_cast(frag->getFirstChild()), buf); + //TS_TRACE(buf.c_str()); + TS_ASSERT(doc->getDocumentElement()->isEqualNode(frag->getFirstChild())); + frag->release(); + doc->release(); + } + catch (XMLToolingException& e) { + TS_TRACE(e.what()); + doc->release(); + throw; + } + } + +}; diff --git a/xmltoolingtest/ExceptionTest.h b/xmltoolingtest/ExceptionTest.h index d290fbe..f7a67b7 100644 --- a/xmltoolingtest/ExceptionTest.h +++ b/xmltoolingtest/ExceptionTest.h @@ -1,49 +1,49 @@ -/* - * Copyright 2001-2005 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. - */ - -#include "XMLObjectBaseTestCase.h" - -#include - - -class ExceptionTest : public CxxTest::TestSuite { -public: - - void testException(void) { -#define TEST(n,b,a) XMLToolingException e##n(b); \ - TS_ASSERT(!strcmp(a,e##n.what())) - -#define TESTP(n,b,a,p) MarshallingException e##n(b,p); \ - TS_ASSERT(!strcmp(a,e##n.what())) - - - TESTP(1,"This is a test.", "This is a test.", params(2,"Foo","bar")); - TESTP(2,"This is a test.$", "This is a test.", params(2,"Foo","bar")); - TESTP(3,"This is a $ test.", "This is a test.", params(2,"Foo","bar")); - TESTP(4,"$$This is a test.$", "$This is a test.", params(2,"Foo","bar")); - TESTP(5,"$This is a $test.", "This is a test.", params(2,"Foo","bar")); - TESTP(6,"$1 is a $2", "Foo is a bar", params(2,"Foo","bar")); - TESTP(7,"$This is a $test.", "Foo is a bar.", namedparams(2,"This","Foo","test","bar")); - TESTP(8,"Unable to generate random data: $1", - "Unable to generate random data: OpenSSLCryptoProvider::getRandom - OpenSSL random not properly initialised", - params(1,"OpenSSLCryptoProvider::getRandom - OpenSSL random not properly initialised")); - - string buf=e7.toString(); - auto_ptr ptr(XMLToolingException::fromString(buf.c_str())); - TS_ASSERT(typeid(*ptr)==typeid(MarshallingException)); - TS_ASSERT(!strcmp(ptr->what(),"Foo is a bar.")); - } -}; +/* + * Copyright 2001-2005 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include + + +class ExceptionTest : public CxxTest::TestSuite { +public: + + void testException(void) { +#define TEST(n,b,a) XMLToolingException e##n(b); \ + TS_ASSERT(!strcmp(a,e##n.what())) + +#define TESTP(n,b,a,p) MarshallingException e##n(b,p); \ + TS_ASSERT(!strcmp(a,e##n.what())) + + + TESTP(1,"This is a test.", "This is a test.", params(2,"Foo","bar")); + TESTP(2,"This is a test.$", "This is a test.", params(2,"Foo","bar")); + TESTP(3,"This is a $ test.", "This is a test.", params(2,"Foo","bar")); + TESTP(4,"$$This is a test.$", "$This is a test.", params(2,"Foo","bar")); + TESTP(5,"$This is a $test.", "This is a test.", params(2,"Foo","bar")); + TESTP(6,"$1 is a $2", "Foo is a bar", params(2,"Foo","bar")); + TESTP(7,"$This is a $test.", "Foo is a bar.", namedparams(2,"This","Foo","test","bar")); + TESTP(8,"Unable to generate random data: $1", + "Unable to generate random data: OpenSSLCryptoProvider::getRandom - OpenSSL random not properly initialised", + params(1,"OpenSSLCryptoProvider::getRandom - OpenSSL random not properly initialised")); + + string buf=e7.toString(); + auto_ptr ptr(XMLToolingException::fromString(buf.c_str())); + TS_ASSERT(typeid(*ptr)==typeid(MarshallingException)); + TS_ASSERT(!strcmp(ptr->what(),"Foo is a bar.")); + } +}; diff --git a/xmltoolingtest/FilesystemCredentialResolverTest.h b/xmltoolingtest/FilesystemCredentialResolverTest.h index 92e720a..7f2816b 100644 --- a/xmltoolingtest/FilesystemCredentialResolverTest.h +++ b/xmltoolingtest/FilesystemCredentialResolverTest.h @@ -1,48 +1,48 @@ -/* - * 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. - */ - -#include "XMLObjectBaseTestCase.h" - -#include - -#include - -class FilesystemCredentialResolverTest : public CxxTest::TestSuite { -public: - void setUp() { - } - - void tearDown() { - } - - void testFilesystemProvider() { - string config = data_path + "FilesystemCredentialResolver.xml"; - ifstream in(config.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); - XercesJanitor janitor(doc); - - auto_ptr credResolver( - XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin( - FILESYSTEM_CREDENTIAL_RESOLVER,doc->getDocumentElement() - ) - ); - - Locker locker(credResolver.get()); - auto_ptr key(credResolver->getKey()); - TSM_ASSERT("Retrieved key was null", key.get()!=NULL); - TSM_ASSERT_EQUALS("Unexpected number of certificates", 1, credResolver->getCertificates().size()); - } -}; +/* + * 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include + +#include + +class FilesystemCredentialResolverTest : public CxxTest::TestSuite { +public: + void setUp() { + } + + void tearDown() { + } + + void testFilesystemProvider() { + string config = data_path + "FilesystemCredentialResolver.xml"; + ifstream in(config.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); + XercesJanitor janitor(doc); + + auto_ptr credResolver( + XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin( + FILESYSTEM_CREDENTIAL_RESOLVER,doc->getDocumentElement() + ) + ); + + Locker locker(credResolver.get()); + auto_ptr key(credResolver->getKey()); + TSM_ASSERT("Retrieved key was null", key.get()!=NULL); + TSM_ASSERT_EQUALS("Unexpected number of certificates", 1, credResolver->getCertificates().size()); + } +}; diff --git a/xmltoolingtest/InlineKeyResolverTest.h b/xmltoolingtest/InlineKeyResolverTest.h index 0a23779..a8e4ef8 100644 --- a/xmltoolingtest/InlineKeyResolverTest.h +++ b/xmltoolingtest/InlineKeyResolverTest.h @@ -1,63 +1,63 @@ -/* - * Copyright 2001-2005 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. - */ - -#include "XMLObjectBaseTestCase.h" - -#include -#include -#include - -using namespace xmlsignature; - -class InlineKeyResolverTest : public CxxTest::TestSuite { - KeyResolver* m_resolver; -public: - InlineKeyResolverTest() : m_resolver(NULL) {} - - void setUp() { - string config = data_path + "InlineKeyResolver.xml"; - ifstream in(config.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); - XercesJanitor janitor(doc); - m_resolver=XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(INLINE_KEY_RESOLVER,doc->getDocumentElement()); - } - - void tearDown() { - delete m_resolver; - m_resolver=NULL; - } - - void testResolver() { - string path=data_path + "KeyInfo1.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getValidatingParser().parse(fs); - TS_ASSERT(doc!=NULL); - const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - auto_ptr kiObject(dynamic_cast(b->buildFromDocument(doc))); - TS_ASSERT(kiObject.get()!=NULL); - - auto_ptr key(m_resolver->resolveKey(kiObject.get())); - TSM_ASSERT("Unable to resolve public key.", key.get()!=NULL); - TSM_ASSERT_EQUALS("Unexpected key type.", key->getKeyType(), XSECCryptoKey::KEY_RSA_PUBLIC); - - auto_ptr crl(m_resolver->resolveCRL(kiObject.get())); - TSM_ASSERT("Unable to resolve CRL.", crl.get()!=NULL); - - KeyResolver::ResolvedCertificates certs; - TSM_ASSERT_EQUALS("Wrong certificate count.", m_resolver->resolveCertificates(kiObject.get(), certs), 1); - } -}; +/* + * Copyright 2001-2005 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include +#include +#include + +using namespace xmlsignature; + +class InlineKeyResolverTest : public CxxTest::TestSuite { + KeyResolver* m_resolver; +public: + InlineKeyResolverTest() : m_resolver(NULL) {} + + void setUp() { + string config = data_path + "InlineKeyResolver.xml"; + ifstream in(config.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); + XercesJanitor janitor(doc); + m_resolver=XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(INLINE_KEY_RESOLVER,doc->getDocumentElement()); + } + + void tearDown() { + delete m_resolver; + m_resolver=NULL; + } + + void testResolver() { + string path=data_path + "KeyInfo1.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getValidatingParser().parse(fs); + TS_ASSERT(doc!=NULL); + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + auto_ptr kiObject(dynamic_cast(b->buildFromDocument(doc))); + TS_ASSERT(kiObject.get()!=NULL); + + auto_ptr key(m_resolver->resolveKey(kiObject.get())); + TSM_ASSERT("Unable to resolve public key.", key.get()!=NULL); + TSM_ASSERT_EQUALS("Unexpected key type.", key->getKeyType(), XSECCryptoKey::KEY_RSA_PUBLIC); + + auto_ptr crl(m_resolver->resolveCRL(kiObject.get())); + TSM_ASSERT("Unable to resolve CRL.", crl.get()!=NULL); + + KeyResolver::ResolvedCertificates certs; + TSM_ASSERT_EQUALS("Wrong certificate count.", m_resolver->resolveCertificates(kiObject.get(), certs), 1); + } +}; diff --git a/xmltoolingtest/KeyInfoTest.h b/xmltoolingtest/KeyInfoTest.h index 0379cae..5f23612 100644 --- a/xmltoolingtest/KeyInfoTest.h +++ b/xmltoolingtest/KeyInfoTest.h @@ -1,95 +1,95 @@ -/* - * Copyright 2001-2005 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. - */ - -#include "XMLObjectBaseTestCase.h" - -#include -#include -#include - -using namespace xmlsignature; - -class KeyInfoTest : public CxxTest::TestSuite { -public: - KeyInfoTest() {} - - void setUp() { - XMLObjectBuilder::registerDefaultBuilder(new AnyElementBuilder()); - } - - void tearDown() { - XMLObjectBuilder::deregisterDefaultBuilder(); - } - - void testKeyInfo1() { - string path=data_path + "KeyInfo1.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getValidatingParser().parse(fs); - TS_ASSERT(doc!=NULL); - - const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - - auto_ptr kiObject(dynamic_cast(b->buildFromDocument(doc))); - TS_ASSERT(kiObject.get()!=NULL); - TSM_ASSERT_EQUALS("Number of child elements was not expected value", - 3, kiObject->getOrderedChildren().size()); - TSM_ASSERT_EQUALS("Number of child elements was not expected value", - 1, kiObject->getKeyValues().size()); - TSM_ASSERT_EQUALS("Number of child elements was not expected value", - 1, kiObject->getX509Datas().front()->getX509Certificates().size()); - - auto_ptr_XMLCh expected("Public Key for CN=xmldap.org, OU=Domain Control Validated, O=xmldap.org"); - TSM_ASSERT("KeyName was not expected value", XMLString::equals(expected.get(), kiObject->getKeyNames().front()->getName())); - - SchemaValidators.validate(kiObject.get()); - } - - void testKeyInfo2() { - string path=data_path + "KeyInfo2.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getValidatingParser().parse(fs); - TS_ASSERT(doc!=NULL); - - const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - - auto_ptr kiObject(dynamic_cast(b->buildFromDocument(doc))); - TS_ASSERT(kiObject.get()!=NULL); - TSM_ASSERT_EQUALS("Number of child elements was not expected value", - 2, kiObject->getOrderedChildren().size()); - TSM_ASSERT_EQUALS("Number of child elements was not expected value", - 1, kiObject->getRetrievalMethods().size()); - TSM_ASSERT_EQUALS("Number of child elements was not expected value", - 2, kiObject->getSPKIDatas().front()->getSPKISexps().size()); - - SchemaValidators.validate(kiObject.get()); - } - - void testKeyInfo3() { - string path=data_path + "KeyInfo3.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - - auto_ptr kiObject(dynamic_cast(b->buildFromDocument(doc))); - TS_ASSERT(kiObject.get()!=NULL); - TS_ASSERT_THROWS(SchemaValidators.validate(kiObject.get()),ValidationException); - } -}; +/* + * Copyright 2001-2005 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include +#include +#include + +using namespace xmlsignature; + +class KeyInfoTest : public CxxTest::TestSuite { +public: + KeyInfoTest() {} + + void setUp() { + XMLObjectBuilder::registerDefaultBuilder(new AnyElementBuilder()); + } + + void tearDown() { + XMLObjectBuilder::deregisterDefaultBuilder(); + } + + void testKeyInfo1() { + string path=data_path + "KeyInfo1.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getValidatingParser().parse(fs); + TS_ASSERT(doc!=NULL); + + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr kiObject(dynamic_cast(b->buildFromDocument(doc))); + TS_ASSERT(kiObject.get()!=NULL); + TSM_ASSERT_EQUALS("Number of child elements was not expected value", + 3, kiObject->getOrderedChildren().size()); + TSM_ASSERT_EQUALS("Number of child elements was not expected value", + 1, kiObject->getKeyValues().size()); + TSM_ASSERT_EQUALS("Number of child elements was not expected value", + 1, kiObject->getX509Datas().front()->getX509Certificates().size()); + + auto_ptr_XMLCh expected("Public Key for CN=xmldap.org, OU=Domain Control Validated, O=xmldap.org"); + TSM_ASSERT("KeyName was not expected value", XMLString::equals(expected.get(), kiObject->getKeyNames().front()->getName())); + + SchemaValidators.validate(kiObject.get()); + } + + void testKeyInfo2() { + string path=data_path + "KeyInfo2.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getValidatingParser().parse(fs); + TS_ASSERT(doc!=NULL); + + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr kiObject(dynamic_cast(b->buildFromDocument(doc))); + TS_ASSERT(kiObject.get()!=NULL); + TSM_ASSERT_EQUALS("Number of child elements was not expected value", + 2, kiObject->getOrderedChildren().size()); + TSM_ASSERT_EQUALS("Number of child elements was not expected value", + 1, kiObject->getRetrievalMethods().size()); + TSM_ASSERT_EQUALS("Number of child elements was not expected value", + 2, kiObject->getSPKIDatas().front()->getSPKISexps().size()); + + SchemaValidators.validate(kiObject.get()); + } + + void testKeyInfo3() { + string path=data_path + "KeyInfo3.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr kiObject(dynamic_cast(b->buildFromDocument(doc))); + TS_ASSERT(kiObject.get()!=NULL); + TS_ASSERT_THROWS(SchemaValidators.validate(kiObject.get()),ValidationException); + } +}; diff --git a/xmltoolingtest/MarshallingTest.h b/xmltoolingtest/MarshallingTest.h index 1a5c53a..0414185 100644 --- a/xmltoolingtest/MarshallingTest.h +++ b/xmltoolingtest/MarshallingTest.h @@ -1,111 +1,111 @@ -/* - * Copyright 2001-2005 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. - */ - -#include "XMLObjectBaseTestCase.h" - -#include - -class MarshallingTest : public CxxTest::TestSuite { -public: - void setUp() { - QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); - QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); - XMLObjectBuilder::registerBuilder(qname, new SimpleXMLObjectBuilder()); - XMLObjectBuilder::registerBuilder(qtype, new SimpleXMLObjectBuilder()); - } - - void tearDown() { - QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); - QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); - XMLObjectBuilder::deregisterBuilder(qname); - XMLObjectBuilder::deregisterBuilder(qtype); - } - - void testMarshallingWithAttributes() { - QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); - auto_ptr sxObject(SimpleXMLObjectBuilder::newSimpleXMLObject()); - TS_ASSERT(sxObject.get()!=NULL); - auto_ptr_XMLCh expected("Firefly"); - sxObject->setId(expected.get()); - - DOMElement* rootElement = sxObject->marshall(); - - string path=data_path + "SimpleXMLObjectWithAttribute.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - TS_ASSERT(rootElement->isEqualNode(doc->getDocumentElement())); - doc->release(); - } - - void testMarshallingWithElementContent() { - QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); - auto_ptr sxObject(SimpleXMLObjectBuilder::newSimpleXMLObject()); - TS_ASSERT(sxObject.get()!=NULL); - auto_ptr_XMLCh expected("Sample Content"); - sxObject->setValue(expected.get()); - - DOMElement* rootElement = sxObject->marshall(); - - string path=data_path + "SimpleXMLObjectWithContent.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - TS_ASSERT(rootElement->isEqualNode(doc->getDocumentElement())); - doc->release(); - } - - void testMarshallingWithChildElements() { - QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); - const SimpleXMLObjectBuilder* b=dynamic_cast(XMLObjectBuilder::getBuilder(qname)); - TS_ASSERT(b!=NULL); - - auto_ptr sxObject(b->buildObject()); - TS_ASSERT(sxObject.get()!=NULL); - VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects(); - kids.push_back(b->buildObject()); - kids.push_back(b->buildObject()); - kids.push_back(b->buildObject()); - - // Test some collection stuff - auto_ptr_XMLCh foo("Foo"); - auto_ptr_XMLCh bar("Bar"); - auto_ptr_XMLCh baz("Baz"); - kids.begin()->setId(foo.get()); - kids.at(2)->setValue(bar.get()); - kids.erase(kids.begin()+1); - TS_ASSERT(XMLString::equals(kids.back()->getValue(), bar.get())); - - QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME,SimpleXMLObject::NAMESPACE_PREFIX); - kids.push_back( - b->buildObject(SimpleXMLObject::NAMESPACE,SimpleXMLObject::DERIVED_NAME,SimpleXMLObject::NAMESPACE_PREFIX,&qtype) - ); - kids.back()->setValue(baz.get()); - - DOMElement* rootElement = sxObject->marshall(); - - string path=data_path + "SimpleXMLObjectWithChildren.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - TS_ASSERT(rootElement->isEqualNode(doc->getDocumentElement())); - doc->release(); - } - -}; +/* + * Copyright 2001-2005 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include + +class MarshallingTest : public CxxTest::TestSuite { +public: + void setUp() { + QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); + QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); + XMLObjectBuilder::registerBuilder(qname, new SimpleXMLObjectBuilder()); + XMLObjectBuilder::registerBuilder(qtype, new SimpleXMLObjectBuilder()); + } + + void tearDown() { + QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); + QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); + XMLObjectBuilder::deregisterBuilder(qname); + XMLObjectBuilder::deregisterBuilder(qtype); + } + + void testMarshallingWithAttributes() { + QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); + auto_ptr sxObject(SimpleXMLObjectBuilder::newSimpleXMLObject()); + TS_ASSERT(sxObject.get()!=NULL); + auto_ptr_XMLCh expected("Firefly"); + sxObject->setId(expected.get()); + + DOMElement* rootElement = sxObject->marshall(); + + string path=data_path + "SimpleXMLObjectWithAttribute.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + TS_ASSERT(rootElement->isEqualNode(doc->getDocumentElement())); + doc->release(); + } + + void testMarshallingWithElementContent() { + QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); + auto_ptr sxObject(SimpleXMLObjectBuilder::newSimpleXMLObject()); + TS_ASSERT(sxObject.get()!=NULL); + auto_ptr_XMLCh expected("Sample Content"); + sxObject->setValue(expected.get()); + + DOMElement* rootElement = sxObject->marshall(); + + string path=data_path + "SimpleXMLObjectWithContent.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + TS_ASSERT(rootElement->isEqualNode(doc->getDocumentElement())); + doc->release(); + } + + void testMarshallingWithChildElements() { + QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); + const SimpleXMLObjectBuilder* b=dynamic_cast(XMLObjectBuilder::getBuilder(qname)); + TS_ASSERT(b!=NULL); + + auto_ptr sxObject(b->buildObject()); + TS_ASSERT(sxObject.get()!=NULL); + VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects(); + kids.push_back(b->buildObject()); + kids.push_back(b->buildObject()); + kids.push_back(b->buildObject()); + + // Test some collection stuff + auto_ptr_XMLCh foo("Foo"); + auto_ptr_XMLCh bar("Bar"); + auto_ptr_XMLCh baz("Baz"); + kids.begin()->setId(foo.get()); + kids.at(2)->setValue(bar.get()); + kids.erase(kids.begin()+1); + TS_ASSERT(XMLString::equals(kids.back()->getValue(), bar.get())); + + QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME,SimpleXMLObject::NAMESPACE_PREFIX); + kids.push_back( + b->buildObject(SimpleXMLObject::NAMESPACE,SimpleXMLObject::DERIVED_NAME,SimpleXMLObject::NAMESPACE_PREFIX,&qtype) + ); + kids.back()->setValue(baz.get()); + + DOMElement* rootElement = sxObject->marshall(); + + string path=data_path + "SimpleXMLObjectWithChildren.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + TS_ASSERT(rootElement->isEqualNode(doc->getDocumentElement())); + doc->release(); + } + +}; diff --git a/xmltoolingtest/MemoryStorageServiceTest.h b/xmltoolingtest/MemoryStorageServiceTest.h index c8f02ee..830e17b 100644 --- a/xmltoolingtest/MemoryStorageServiceTest.h +++ b/xmltoolingtest/MemoryStorageServiceTest.h @@ -1,46 +1,46 @@ -/* - * 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. - */ - -#include "XMLObjectBaseTestCase.h" - -#include - -class MemoryStorageServiceTest : public CxxTest::TestSuite { -public: - void setUp() { - } - - void tearDown() { - } - - void testMemoryService() { - auto_ptr storage( - XMLToolingConfig::getConfig().StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE,NULL) - ); - - string data; - TSM_ASSERT("Record found in storage.", !storage->readString("context", "foo1", &data)); - storage->createString("context", "foo1", "bar1", time(NULL) + 60); - storage->createString("context", "foo2", "bar2", time(NULL) + 60); - TSM_ASSERT("Record not found in storage.", storage->readString("context", "foo1", &data)); - TSM_ASSERT_EQUALS("Record value doesn't match.", data, "bar1"); - TSM_ASSERT("Update failed.", storage->updateString("context", "foo2", "bar1")); - TSM_ASSERT("Record not found in storage.", storage->readString("context", "foo2", &data)); - TSM_ASSERT_EQUALS("Record value doesn't match.", data, "bar1"); - TSM_ASSERT("Delete failed.", storage->deleteString("context", "foo2")); - storage->reap("context"); - } -}; +/* + * 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include + +class MemoryStorageServiceTest : public CxxTest::TestSuite { +public: + void setUp() { + } + + void tearDown() { + } + + void testMemoryService() { + auto_ptr storage( + XMLToolingConfig::getConfig().StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE,NULL) + ); + + string data; + TSM_ASSERT("Record found in storage.", !storage->readString("context", "foo1", &data)); + storage->createString("context", "foo1", "bar1", time(NULL) + 60); + storage->createString("context", "foo2", "bar2", time(NULL) + 60); + TSM_ASSERT("Record not found in storage.", storage->readString("context", "foo1", &data)); + TSM_ASSERT_EQUALS("Record value doesn't match.", data, "bar1"); + TSM_ASSERT("Update failed.", storage->updateString("context", "foo2", "bar1")); + TSM_ASSERT("Record not found in storage.", storage->readString("context", "foo2", &data)); + TSM_ASSERT_EQUALS("Record value doesn't match.", data, "bar1"); + TSM_ASSERT("Delete failed.", storage->deleteString("context", "foo2")); + storage->reap("context"); + } +}; diff --git a/xmltoolingtest/SignatureTest.h b/xmltoolingtest/SignatureTest.h index c1ca7ec..a733767 100644 --- a/xmltoolingtest/SignatureTest.h +++ b/xmltoolingtest/SignatureTest.h @@ -1,169 +1,169 @@ -/* - * Copyright 2001-2005 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. - */ - -#include "XMLObjectBaseTestCase.h" - -#include -#include -#include - -#include -#include -#include - -class TestContext : public ContentReference -{ - XMLCh* m_uri; - -public: - TestContext(const XMLCh* uri) { - m_uri=XMLString::replicate(uri); - } - - virtual ~TestContext() { - XMLString::release(&m_uri); - } - - void createReferences(DSIGSignature* sig) { - DSIGReference* ref=sig->createReference(m_uri); - ref->appendEnvelopedSignatureTransform(); - ref->appendCanonicalizationTransform(CANON_C14NE_NOC); - } -}; - -class TestValidator : public SignatureValidator -{ - XMLCh* m_uri; - -public: - TestValidator(const XMLCh* uri) : SignatureValidator(XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(INLINE_KEY_RESOLVER,NULL)) { - m_uri=XMLString::replicate(uri); - } - - virtual ~TestValidator() { - XMLString::release(&m_uri); - } - - void validate(const Signature* sigObj) const { - DSIGSignature* sig=sigObj->getXMLSignature(); - if (!sig) - throw SignatureException("Only a marshalled Signature object can be verified."); - const XMLCh* uri=sig->getReferenceList()->item(0)->getURI(); - TSM_ASSERT_SAME_DATA("Reference URI does not match.",uri,m_uri,XMLString::stringLen(uri)); - SignatureValidator::validate(sigObj); - } -}; - -class _addcert : public std::binary_function { -public: - void operator()(X509Data* bag, XSECCryptoX509* cert) const { - safeBuffer& buf=cert->getDEREncodingSB(); - X509Certificate* x=X509CertificateBuilder::buildX509Certificate(); - x->setValue(buf.sbStrToXMLCh()); - bag->getX509Certificates().push_back(x); - } -}; - -class SignatureTest : public CxxTest::TestSuite { - CredentialResolver* m_resolver; -public: - void setUp() { - m_resolver=NULL; - QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); - QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); - XMLObjectBuilder::registerBuilder(qname, new SimpleXMLObjectBuilder()); - XMLObjectBuilder::registerBuilder(qtype, new SimpleXMLObjectBuilder()); - - string config = data_path + "FilesystemCredentialResolver.xml"; - ifstream in(config.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); - XercesJanitor janitor(doc); - m_resolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin( - FILESYSTEM_CREDENTIAL_RESOLVER,doc->getDocumentElement() - ); - } - - void tearDown() { - QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); - QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); - XMLObjectBuilder::deregisterBuilder(qname); - XMLObjectBuilder::deregisterBuilder(qtype); - delete m_resolver; - } - - void testSignature() { - QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); - const SimpleXMLObjectBuilder* b=dynamic_cast(XMLObjectBuilder::getBuilder(qname)); - TS_ASSERT(b!=NULL); - - auto_ptr sxObject(b->buildObject()); - TS_ASSERT(sxObject.get()!=NULL); - VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects(); - kids.push_back(b->buildObject()); - kids.push_back(b->buildObject()); - - // Test some collection stuff - auto_ptr_XMLCh foo("Foo"); - auto_ptr_XMLCh bar("Bar"); - kids.begin()->setId(foo.get()); - kids[1]->setValue(bar.get()); - - // Append a Signature. - Signature* sig=SignatureBuilder::buildSignature(); - sxObject->setSignature(sig); - sig->setContentReference(new TestContext(&chNull)); - - Locker locker(m_resolver); - sig->setSigningKey(m_resolver->getKey()); - - // Build KeyInfo. - KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo(); - X509Data* x509Data=X509DataBuilder::buildX509Data(); - keyInfo->getX509Datas().push_back(x509Data); - for_each(m_resolver->getCertificates().begin(),m_resolver->getCertificates().end(),bind1st(_addcert(),x509Data)); - sig->setKeyInfo(keyInfo); - - DOMElement* rootElement = NULL; - try { - rootElement=sxObject->marshall((DOMDocument*)NULL); - sig->sign(); - } - catch (XMLToolingException& e) { - TS_TRACE(e.what()); - throw; - } - - string buf; - XMLHelper::serialize(rootElement, buf); - //TS_TRACE(buf.c_str()); - - istringstream in(buf); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); - auto_ptr sxObject2(dynamic_cast(b->buildFromDocument(doc))); - TS_ASSERT(sxObject2.get()!=NULL); - TS_ASSERT(sxObject2->getSignature()!=NULL); - - try { - TestValidator tv(&chNull); - tv.validate(sxObject2->getSignature()); - } - catch (XMLToolingException& e) { - TS_TRACE(e.what()); - throw; - } - } - -}; +/* + * Copyright 2001-2005 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include +#include +#include + +#include +#include +#include + +class TestContext : public ContentReference +{ + XMLCh* m_uri; + +public: + TestContext(const XMLCh* uri) { + m_uri=XMLString::replicate(uri); + } + + virtual ~TestContext() { + XMLString::release(&m_uri); + } + + void createReferences(DSIGSignature* sig) { + DSIGReference* ref=sig->createReference(m_uri); + ref->appendEnvelopedSignatureTransform(); + ref->appendCanonicalizationTransform(CANON_C14NE_NOC); + } +}; + +class TestValidator : public SignatureValidator +{ + XMLCh* m_uri; + +public: + TestValidator(const XMLCh* uri) : SignatureValidator(XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(INLINE_KEY_RESOLVER,NULL)) { + m_uri=XMLString::replicate(uri); + } + + virtual ~TestValidator() { + XMLString::release(&m_uri); + } + + void validate(const Signature* sigObj) const { + DSIGSignature* sig=sigObj->getXMLSignature(); + if (!sig) + throw SignatureException("Only a marshalled Signature object can be verified."); + const XMLCh* uri=sig->getReferenceList()->item(0)->getURI(); + TSM_ASSERT_SAME_DATA("Reference URI does not match.",uri,m_uri,XMLString::stringLen(uri)); + SignatureValidator::validate(sigObj); + } +}; + +class _addcert : public std::binary_function { +public: + void operator()(X509Data* bag, XSECCryptoX509* cert) const { + safeBuffer& buf=cert->getDEREncodingSB(); + X509Certificate* x=X509CertificateBuilder::buildX509Certificate(); + x->setValue(buf.sbStrToXMLCh()); + bag->getX509Certificates().push_back(x); + } +}; + +class SignatureTest : public CxxTest::TestSuite { + CredentialResolver* m_resolver; +public: + void setUp() { + m_resolver=NULL; + QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); + QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); + XMLObjectBuilder::registerBuilder(qname, new SimpleXMLObjectBuilder()); + XMLObjectBuilder::registerBuilder(qtype, new SimpleXMLObjectBuilder()); + + string config = data_path + "FilesystemCredentialResolver.xml"; + ifstream in(config.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); + XercesJanitor janitor(doc); + m_resolver = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin( + FILESYSTEM_CREDENTIAL_RESOLVER,doc->getDocumentElement() + ); + } + + void tearDown() { + QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); + QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); + XMLObjectBuilder::deregisterBuilder(qname); + XMLObjectBuilder::deregisterBuilder(qtype); + delete m_resolver; + } + + void testSignature() { + QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); + const SimpleXMLObjectBuilder* b=dynamic_cast(XMLObjectBuilder::getBuilder(qname)); + TS_ASSERT(b!=NULL); + + auto_ptr sxObject(b->buildObject()); + TS_ASSERT(sxObject.get()!=NULL); + VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects(); + kids.push_back(b->buildObject()); + kids.push_back(b->buildObject()); + + // Test some collection stuff + auto_ptr_XMLCh foo("Foo"); + auto_ptr_XMLCh bar("Bar"); + kids.begin()->setId(foo.get()); + kids[1]->setValue(bar.get()); + + // Append a Signature. + Signature* sig=SignatureBuilder::buildSignature(); + sxObject->setSignature(sig); + sig->setContentReference(new TestContext(&chNull)); + + Locker locker(m_resolver); + sig->setSigningKey(m_resolver->getKey()); + + // Build KeyInfo. + KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo(); + X509Data* x509Data=X509DataBuilder::buildX509Data(); + keyInfo->getX509Datas().push_back(x509Data); + for_each(m_resolver->getCertificates().begin(),m_resolver->getCertificates().end(),bind1st(_addcert(),x509Data)); + sig->setKeyInfo(keyInfo); + + DOMElement* rootElement = NULL; + try { + rootElement=sxObject->marshall((DOMDocument*)NULL); + sig->sign(); + } + catch (XMLToolingException& e) { + TS_TRACE(e.what()); + throw; + } + + string buf; + XMLHelper::serialize(rootElement, buf); + //TS_TRACE(buf.c_str()); + + istringstream in(buf); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in); + auto_ptr sxObject2(dynamic_cast(b->buildFromDocument(doc))); + TS_ASSERT(sxObject2.get()!=NULL); + TS_ASSERT(sxObject2->getSignature()!=NULL); + + try { + TestValidator tv(&chNull); + tv.validate(sxObject2->getSignature()); + } + catch (XMLToolingException& e) { + TS_TRACE(e.what()); + throw; + } + } + +}; diff --git a/xmltoolingtest/UnmarshallingTest.h b/xmltoolingtest/UnmarshallingTest.h index b645f11..255168c 100644 --- a/xmltoolingtest/UnmarshallingTest.h +++ b/xmltoolingtest/UnmarshallingTest.h @@ -1,162 +1,162 @@ -/* - * Copyright 2001-2005 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. - */ - -#include "XMLObjectBaseTestCase.h" - -#include -#include - -const XMLCh SimpleXMLObject::NAMESPACE[] = { - chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, - chLatin_w, chLatin_w, chLatin_w, chPeriod, - chLatin_e, chLatin_x, chLatin_a, chLatin_m, chLatin_p, chLatin_l, chLatin_e, chPeriod, - chLatin_o, chLatin_r, chLatin_g, chForwardSlash, - chLatin_t, chLatin_e, chLatin_s, chLatin_t, - chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_s, chNull -}; - -const XMLCh SimpleXMLObject::NAMESPACE_PREFIX[] = { - chLatin_t, chLatin_e, chLatin_s, chLatin_t, chNull -}; - -const XMLCh SimpleXMLObject::LOCAL_NAME[] = { - chLatin_S, chLatin_i, chLatin_m, chLatin_p, chLatin_l, chLatin_e, - chLatin_E, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chNull -}; - -const XMLCh SimpleXMLObject::DERIVED_NAME[] = { - chLatin_D, chLatin_e, chLatin_r, chLatin_i, chLatin_v, chLatin_e, chLatin_d, - chLatin_E, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chNull -}; - -const XMLCh SimpleXMLObject::TYPE_NAME[] = { - chLatin_S, chLatin_i, chLatin_m, chLatin_p, chLatin_l, chLatin_e, - chLatin_E, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, - chLatin_T, chLatin_y, chLatin_p, chLatin_e, chNull -}; - -const XMLCh SimpleXMLObject::ID_ATTRIB_NAME[] = { - chLatin_I, chLatin_d, chNull -}; - -class UnmarshallingTest : public CxxTest::TestSuite { -public: - void setUp() { - QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); - QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); - XMLObjectBuilder::registerBuilder(qname, new SimpleXMLObjectBuilder()); - XMLObjectBuilder::registerBuilder(qtype, new SimpleXMLObjectBuilder()); - } - - void tearDown() { - QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); - QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); - XMLObjectBuilder::deregisterBuilder(qname); - XMLObjectBuilder::deregisterBuilder(qtype); - } - - void testUnmarshallingWithAttributes() { - string path=data_path + "SimpleXMLObjectWithAttribute.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - - auto_ptr sxObject( - dynamic_cast(b->buildFromDocument(doc)) - ); - TS_ASSERT(sxObject.get()!=NULL); - - auto_ptr_XMLCh expected("Firefly"); - TSM_ASSERT("ID was not expected value", XMLString::equals(expected.get(), sxObject->getId())); - } - - void testUnmarshallingWithElementContent() { - string path=data_path + "SimpleXMLObjectWithContent.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - - auto_ptr sxObject( - dynamic_cast(b->buildFromDocument(doc)) - ); - TS_ASSERT(sxObject.get()!=NULL); - - auto_ptr_XMLCh expected("Sample Content"); - TSM_ASSERT("Element content was not expected value", XMLString::equals(expected.get(), sxObject->getValue())); - } - - void testUnmarshallingWithChildElements() { - string path=data_path + "SimpleXMLObjectWithChildren.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - - auto_ptr sxObject( - dynamic_cast(b->buildFromDocument(doc)) - ); - TS_ASSERT(sxObject.get()!=NULL); - - VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects(); - TSM_ASSERT_EQUALS("Number of child elements was not expected value", 3, kids.size()); - QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); - TSM_ASSERT_EQUALS("Child's schema type was not expected value", qtype, *(kids.back()->getSchemaType())); - } - - void testUnmarshallingWithClone() { - string path=data_path + "SimpleXMLObjectWithChildren.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - - auto_ptr sxObject( - dynamic_cast(b->buildFromDocument(doc)) - ); - TS_ASSERT(sxObject.get()!=NULL); - - sxObject->releaseThisAndChildrenDOM(); - auto_ptr clonedObject(sxObject->clone()); - - VectorOf(SimpleXMLObject) kids=clonedObject->getSimpleXMLObjects(); - TSM_ASSERT_EQUALS("Number of child elements was not expected value", 3, kids.size()); - QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); - TSM_ASSERT_EQUALS("Child's schema type was not expected value", qtype, *(kids.back()->getSchemaType())); - } - - void testUnmarshallingWithUnknownChild() { - string path=data_path + "SimpleXMLObjectWithUnknownChild.xml"; - ifstream fs(path.c_str()); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - - TS_ASSERT_THROWS(b->buildFromDocument(doc),UnmarshallingException); - doc->release(); - } -}; +/* + * Copyright 2001-2005 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include +#include + +const XMLCh SimpleXMLObject::NAMESPACE[] = { + chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash, + chLatin_w, chLatin_w, chLatin_w, chPeriod, + chLatin_e, chLatin_x, chLatin_a, chLatin_m, chLatin_p, chLatin_l, chLatin_e, chPeriod, + chLatin_o, chLatin_r, chLatin_g, chForwardSlash, + chLatin_t, chLatin_e, chLatin_s, chLatin_t, + chLatin_O, chLatin_b, chLatin_j, chLatin_e, chLatin_c, chLatin_t, chLatin_s, chNull +}; + +const XMLCh SimpleXMLObject::NAMESPACE_PREFIX[] = { + chLatin_t, chLatin_e, chLatin_s, chLatin_t, chNull +}; + +const XMLCh SimpleXMLObject::LOCAL_NAME[] = { + chLatin_S, chLatin_i, chLatin_m, chLatin_p, chLatin_l, chLatin_e, + chLatin_E, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chNull +}; + +const XMLCh SimpleXMLObject::DERIVED_NAME[] = { + chLatin_D, chLatin_e, chLatin_r, chLatin_i, chLatin_v, chLatin_e, chLatin_d, + chLatin_E, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chNull +}; + +const XMLCh SimpleXMLObject::TYPE_NAME[] = { + chLatin_S, chLatin_i, chLatin_m, chLatin_p, chLatin_l, chLatin_e, + chLatin_E, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, + chLatin_T, chLatin_y, chLatin_p, chLatin_e, chNull +}; + +const XMLCh SimpleXMLObject::ID_ATTRIB_NAME[] = { + chLatin_I, chLatin_d, chNull +}; + +class UnmarshallingTest : public CxxTest::TestSuite { +public: + void setUp() { + QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); + QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); + XMLObjectBuilder::registerBuilder(qname, new SimpleXMLObjectBuilder()); + XMLObjectBuilder::registerBuilder(qtype, new SimpleXMLObjectBuilder()); + } + + void tearDown() { + QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); + QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); + XMLObjectBuilder::deregisterBuilder(qname); + XMLObjectBuilder::deregisterBuilder(qtype); + } + + void testUnmarshallingWithAttributes() { + string path=data_path + "SimpleXMLObjectWithAttribute.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr sxObject( + dynamic_cast(b->buildFromDocument(doc)) + ); + TS_ASSERT(sxObject.get()!=NULL); + + auto_ptr_XMLCh expected("Firefly"); + TSM_ASSERT("ID was not expected value", XMLString::equals(expected.get(), sxObject->getId())); + } + + void testUnmarshallingWithElementContent() { + string path=data_path + "SimpleXMLObjectWithContent.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr sxObject( + dynamic_cast(b->buildFromDocument(doc)) + ); + TS_ASSERT(sxObject.get()!=NULL); + + auto_ptr_XMLCh expected("Sample Content"); + TSM_ASSERT("Element content was not expected value", XMLString::equals(expected.get(), sxObject->getValue())); + } + + void testUnmarshallingWithChildElements() { + string path=data_path + "SimpleXMLObjectWithChildren.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr sxObject( + dynamic_cast(b->buildFromDocument(doc)) + ); + TS_ASSERT(sxObject.get()!=NULL); + + VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects(); + TSM_ASSERT_EQUALS("Number of child elements was not expected value", 3, kids.size()); + QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); + TSM_ASSERT_EQUALS("Child's schema type was not expected value", qtype, *(kids.back()->getSchemaType())); + } + + void testUnmarshallingWithClone() { + string path=data_path + "SimpleXMLObjectWithChildren.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr sxObject( + dynamic_cast(b->buildFromDocument(doc)) + ); + TS_ASSERT(sxObject.get()!=NULL); + + sxObject->releaseThisAndChildrenDOM(); + auto_ptr clonedObject(sxObject->clone()); + + VectorOf(SimpleXMLObject) kids=clonedObject->getSimpleXMLObjects(); + TSM_ASSERT_EQUALS("Number of child elements was not expected value", 3, kids.size()); + QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); + TSM_ASSERT_EQUALS("Child's schema type was not expected value", qtype, *(kids.back()->getSchemaType())); + } + + void testUnmarshallingWithUnknownChild() { + string path=data_path + "SimpleXMLObjectWithUnknownChild.xml"; + ifstream fs(path.c_str()); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + TS_ASSERT_THROWS(b->buildFromDocument(doc),UnmarshallingException); + doc->release(); + } +}; diff --git a/xmltoolingtest/xmltoolingtest.h b/xmltoolingtest/xmltoolingtest.h index 6507143..dc76d97 100644 --- a/xmltoolingtest/xmltoolingtest.h +++ b/xmltoolingtest/xmltoolingtest.h @@ -1,126 +1,126 @@ -/* - * Copyright 2001-2005 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. - */ - -#include "XMLObjectBaseTestCase.h" - -#include -#include -#include -#include - -//#define XMLTOOLINGTEST_LEAKCHECK - -std::string data_path = "../xmltoolingtest/data/"; - -class ToolingFixture : public CxxTest::GlobalFixture -{ -public: - bool setUpWorld() { - XMLToolingConfig::getConfig().log_config(); - - if (getenv("XMLTOOLINGTEST_DATA")) - data_path=std::string(getenv("XMLTOOLINGTEST_DATA")) + "/"; - XMLToolingConfig::getConfig().catalog_path = data_path + "catalog.xml"; - - if (!XMLToolingConfig::getConfig().init()) - return false; - - return true; - } - bool tearDownWorld() { - XMLToolingConfig::getConfig().term(); -#if defined(_MSC_VER ) && defined(XMLTOOLINGTEST_LEAKCHECK) - _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); - _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); - _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); - _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); - _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); - _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); - _CrtDumpMemoryLeaks(); -#endif - return true; - } - //bool setUp() { printf( "" ); return true; } - //bool tearDown() { printf( "" ); return true; } -}; - -static ToolingFixture globalFixture; - -class GlobalTest : public CxxTest::TestSuite -{ -public: - void setUp() { - XMLObjectBuilder::registerDefaultBuilder(new UnknownElementBuilder()); - } - - void tearDown() { - XMLObjectBuilder::deregisterDefaultBuilder(); - } - - void testUnknown() { - ifstream fs("../xmltoolingtest/data/SimpleXMLObjectWithChildren.xml"); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - string buf1; - XMLHelper::serialize(doc->getDocumentElement(), buf1); - - const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - - auto_ptr xmlObject(b->buildFromDocument(doc)); // bind document - TS_ASSERT(xmlObject.get()!=NULL); - - auto_ptr clonedObject(xmlObject->clone()); - TS_ASSERT(clonedObject.get()!=NULL); - - DOMElement* rootElement=clonedObject->marshall(); - TS_ASSERT(rootElement!=NULL); - - // should reuse DOM - TS_ASSERT(rootElement==clonedObject->marshall()); - - string buf2; - XMLHelper::serialize(rootElement, buf2); - TS_ASSERT_EQUALS(buf1,buf2); - } - - void testUnknownWithDocChange() { - ifstream fs("../xmltoolingtest/data/SimpleXMLObjectWithChildren.xml"); - DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); - TS_ASSERT(doc!=NULL); - - string buf1; - XMLHelper::serialize(doc->getDocumentElement(), buf1); - - const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(doc->getDocumentElement()); - TS_ASSERT(b!=NULL); - - auto_ptr xmlObject(b->buildFromDocument(doc)); // bind document - TS_ASSERT(xmlObject.get()!=NULL); - - DOMDocument* newDoc=XMLToolingConfig::getConfig().getParser().newDocument(); - DOMElement* rootElement=xmlObject->marshall(newDoc); - TS_ASSERT(rootElement!=NULL); - - string buf2; - XMLHelper::serialize(rootElement, buf2); - TS_ASSERT_EQUALS(buf1,buf2); - - newDoc->release(); - } -}; - +/* + * Copyright 2001-2005 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. + */ + +#include "XMLObjectBaseTestCase.h" + +#include +#include +#include +#include + +//#define XMLTOOLINGTEST_LEAKCHECK + +std::string data_path = "../xmltoolingtest/data/"; + +class ToolingFixture : public CxxTest::GlobalFixture +{ +public: + bool setUpWorld() { + XMLToolingConfig::getConfig().log_config(); + + if (getenv("XMLTOOLINGTEST_DATA")) + data_path=std::string(getenv("XMLTOOLINGTEST_DATA")) + "/"; + XMLToolingConfig::getConfig().catalog_path = data_path + "catalog.xml"; + + if (!XMLToolingConfig::getConfig().init()) + return false; + + return true; + } + bool tearDownWorld() { + XMLToolingConfig::getConfig().term(); +#if defined(_MSC_VER ) && defined(XMLTOOLINGTEST_LEAKCHECK) + _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); + _CrtDumpMemoryLeaks(); +#endif + return true; + } + //bool setUp() { printf( "" ); return true; } + //bool tearDown() { printf( "" ); return true; } +}; + +static ToolingFixture globalFixture; + +class GlobalTest : public CxxTest::TestSuite +{ +public: + void setUp() { + XMLObjectBuilder::registerDefaultBuilder(new UnknownElementBuilder()); + } + + void tearDown() { + XMLObjectBuilder::deregisterDefaultBuilder(); + } + + void testUnknown() { + ifstream fs("../xmltoolingtest/data/SimpleXMLObjectWithChildren.xml"); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + string buf1; + XMLHelper::serialize(doc->getDocumentElement(), buf1); + + const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr xmlObject(b->buildFromDocument(doc)); // bind document + TS_ASSERT(xmlObject.get()!=NULL); + + auto_ptr clonedObject(xmlObject->clone()); + TS_ASSERT(clonedObject.get()!=NULL); + + DOMElement* rootElement=clonedObject->marshall(); + TS_ASSERT(rootElement!=NULL); + + // should reuse DOM + TS_ASSERT(rootElement==clonedObject->marshall()); + + string buf2; + XMLHelper::serialize(rootElement, buf2); + TS_ASSERT_EQUALS(buf1,buf2); + } + + void testUnknownWithDocChange() { + ifstream fs("../xmltoolingtest/data/SimpleXMLObjectWithChildren.xml"); + DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(fs); + TS_ASSERT(doc!=NULL); + + string buf1; + XMLHelper::serialize(doc->getDocumentElement(), buf1); + + const XMLObjectBuilder* b=XMLObjectBuilder::getBuilder(doc->getDocumentElement()); + TS_ASSERT(b!=NULL); + + auto_ptr xmlObject(b->buildFromDocument(doc)); // bind document + TS_ASSERT(xmlObject.get()!=NULL); + + DOMDocument* newDoc=XMLToolingConfig::getConfig().getParser().newDocument(); + DOMElement* rootElement=xmlObject->marshall(newDoc); + TS_ASSERT(rootElement!=NULL); + + string buf2; + XMLHelper::serialize(rootElement, buf2); + TS_ASSERT_EQUALS(buf1,buf2); + + newDoc->release(); + } +}; +