Add XML Attribute classes.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Sun, 7 Jun 2009 19:26:08 +0000 (19:26 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Sun, 7 Jun 2009 19:26:08 +0000 (19:26 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/branches/REL_2@3037 cb58f699-b61c-0410-a6fe-9272a202ed29

shibsp/Makefile.am
shibsp/attribute/Attribute.cpp
shibsp/attribute/AttributeDecoder.h
shibsp/attribute/XMLAttribute.h [new file with mode: 0644]
shibsp/attribute/XMLAttributeDecoder.cpp [new file with mode: 0644]
shibsp/shibsp-lite.vcproj
shibsp/shibsp.vcproj

index 08b03a2..45933ac 100644 (file)
@@ -46,7 +46,8 @@ attrinclude_HEADERS = \
        attribute/ExtensibleAttribute.h \
        attribute/NameIDAttribute.h \
        attribute/ScopedAttribute.h \
-       attribute/SimpleAttribute.h
+       attribute/SimpleAttribute.h \
+       attribute/XMLAttribute.h
 
 attrfiltinclude_HEADERS = \
        attribute/filtering/AttributeFilter.h \
@@ -159,6 +160,7 @@ libshibsp_la_SOURCES = \
        attribute/NameIDFromScopedAttributeDecoder.cpp \
        attribute/ScopedAttributeDecoder.cpp \
        attribute/StringAttributeDecoder.cpp \
+       attribute/XMLAttributeDecoder.cpp \
        attribute/filtering/impl/AttributeFilter.cpp \
        attribute/filtering/impl/ChainingAttributeFilter.cpp \
        attribute/filtering/impl/XMLAttributeFilter.cpp \
index 82c7f6d..36c32bc 100644 (file)
 #include "attribute/ScopedAttribute.h"
 #include "attribute/NameIDAttribute.h"
 #include "attribute/ExtensibleAttribute.h"
+#include "attribute/XMLAttribute.h"
 #include "util/SPConstants.h"
 
+#include <xercesc/util/Base64.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 
 using namespace shibsp;
@@ -55,6 +57,10 @@ namespace shibsp {
         return new ExtensibleAttribute(in);
     }
 
+    SHIBSP_DLLLOCAL Attribute* XMLAttributeFactory(DDF& in) {
+        return new XMLAttribute(in);
+    }
+
 #ifndef SHIBSP_LITE
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory StringAttributeDecoderFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory ScopedAttributeDecoderFactory;
@@ -62,6 +68,7 @@ namespace shibsp {
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory NameIDFromScopedAttributeDecoderFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory KeyInfoAttributeDecoderFactory;
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory DOMAttributeDecoderFactory;
+    SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory XMLAttributeDecoderFactory;
 
     static const XMLCh _StringAttributeDecoder[] = UNICODE_LITERAL_22(S,t,r,i,n,g,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _ScopedAttributeDecoder[] = UNICODE_LITERAL_22(S,c,o,p,e,d,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
@@ -69,6 +76,7 @@ namespace shibsp {
     static const XMLCh _NameIDFromScopedAttributeDecoder[] = UNICODE_LITERAL_32(N,a,m,e,I,D,F,r,o,m,S,c,o,p,e,d,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _KeyInfoAttributeDecoder[] =UNICODE_LITERAL_23(K,e,y,I,n,f,o,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
     static const XMLCh _DOMAttributeDecoder[] =    UNICODE_LITERAL_19(D,O,M,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
+    static const XMLCh _XMLAttributeDecoder[] =    UNICODE_LITERAL_19(X,M,L,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
 
     static const XMLCh caseSensitive[] =           UNICODE_LITERAL_13(c,a,s,e,S,e,n,s,i,t,i,v,e);
     static const XMLCh internal[] =                UNICODE_LITERAL_8(i,n,t,e,r,n,a,l);
@@ -82,6 +90,7 @@ xmltooling::QName shibsp::NameIDAttributeDecoderType(shibspconstants::SHIB2ATTRI
 xmltooling::QName shibsp::NameIDFromScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDFromScopedAttributeDecoder);
 xmltooling::QName shibsp::KeyInfoAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _KeyInfoAttributeDecoder);
 xmltooling::QName shibsp::DOMAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _DOMAttributeDecoder);
+xmltooling::QName shibsp::XMLAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _XMLAttributeDecoder);
 
 void shibsp::registerAttributeDecoders()
 {
@@ -92,6 +101,7 @@ void shibsp::registerAttributeDecoders()
     conf.AttributeDecoderManager.registerFactory(NameIDFromScopedAttributeDecoderType, NameIDFromScopedAttributeDecoderFactory);
     conf.AttributeDecoderManager.registerFactory(KeyInfoAttributeDecoderType, KeyInfoAttributeDecoderFactory);
     conf.AttributeDecoderManager.registerFactory(DOMAttributeDecoderType, DOMAttributeDecoderFactory);
+    conf.AttributeDecoderManager.registerFactory(XMLAttributeDecoderType, XMLAttributeDecoderFactory);
 }
 
 AttributeDecoder::AttributeDecoder(const DOMElement *e) : m_caseSensitive(true), m_internal(false)
@@ -115,6 +125,7 @@ void shibsp::registerAttributeFactories()
     Attribute::registerFactory("Scoped", ScopedAttributeFactory);
     Attribute::registerFactory("NameID", NameIDAttributeFactory);
     Attribute::registerFactory("Extensible", ExtensibleAttributeFactory);
+    Attribute::registerFactory("XML", XMLAttributeFactory);
 }
 
 map<string,Attribute::AttributeFactory*> Attribute::m_factoryMap;
@@ -162,3 +173,27 @@ Attribute* Attribute::unmarshall(DDF& in)
         throw AttributeException("No registered factory for Attribute of type ($1).", params(1,in.name()));
     return (i->second)(in);
 }
+
+const vector<string>& XMLAttribute::getSerializedValues() const
+{
+    xsecsize_t len;
+    XMLByte *pos, *pos2;\r
+    if (m_serialized.empty()) {
+        for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
+            XMLByte* enc = Base64::encode(reinterpret_cast<const XMLByte*>(i->data()), i->size(), &len);
+            if (enc) {
+                for (pos=enc, pos2=enc; *pos2; pos2++)\r
+                    if (isgraph(*pos2))\r
+                        *pos++=*pos2;\r
+                *pos=0;\r
+                m_serialized.push_back(reinterpret_cast<char*>(enc));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+                XMLString::release(&enc);
+#else
+                XMLString::release((char**)&enc);
+#endif
+            }
+        }
+    }
+    return Attribute::getSerializedValues();
+}
index 6a9ca7a..5b0ad48 100644 (file)
@@ -99,6 +99,9 @@ namespace shibsp {
     /** Decodes arbitrary DOM information into an ExtensibleAttribute. */
     extern SHIBSP_API xmltooling::QName DOMAttributeDecoderType;
 
+    /** Decodes arbitrary XML into an XMLAttribute. */
+    extern SHIBSP_API xmltooling::QName XMLAttributeDecoderType;
+
     /** Registers built-in AttributeDecoders into the runtime. */
     void registerAttributeDecoders();
 };
diff --git a/shibsp/attribute/XMLAttribute.h b/shibsp/attribute/XMLAttribute.h
new file mode 100644 (file)
index 0000000..3c9a4f6
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *  Copyright 2009 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 shibsp/attribute/XMLAttribute.h
+ *
+ * An Attribute whose values are serialized XML.
+ */
+
+#ifndef __shibsp_xmlattr_h__
+#define __shibsp_xmlattr_h__
+
+#include <shibsp/attribute/Attribute.h>
+
+namespace shibsp {
+
+    /**
+     * An Attribute whose values are serialized XML.
+     */
+    class SHIBSP_API XMLAttribute : public Attribute
+    {
+    public:
+        /**
+         * Constructor.
+         *
+         * @param ids   array with primary identifier in first position, followed by any aliases
+         */
+        XMLAttribute(const std::vector<std::string>& ids) : Attribute(ids) {}
+
+        /**
+         * Constructs based on a remoted XMLAttribute.
+         *
+         * @param in    input object containing marshalled XMLAttribute
+         */
+        XMLAttribute(DDF& in) : Attribute(in) {
+            DDF val = in.first().first();
+            while (val.string()) {
+                m_values.push_back(val.string());
+                val = in.first().next();
+            }
+        }
+
+        virtual ~XMLAttribute() {}
+
+        /**
+         * Returns the set of values encoded as XML.
+         *
+         * @return  a mutable vector of the values
+         */
+        std::vector<std::string>& getValues() {
+            return m_values;
+        }
+
+        /**
+         * Returns the set of values encoded as XML.
+         *
+         * @return  an immutable vector of the values
+         */
+        const std::vector<std::string>& getValues() const {
+            return m_values;
+        }
+
+        size_t valueCount() const {
+            return m_values.size();
+        }
+
+        void clearSerializedValues() {
+            m_serialized.clear();
+        }
+
+        const char* getString(size_t index) const {
+            return m_values[index].c_str();
+        }
+
+        void removeValue(size_t index) {
+            Attribute::removeValue(index);
+            if (index < m_values.size())
+                m_values.erase(m_values.begin() + index);
+        }
+
+        const std::vector<std::string>& getSerializedValues() const;
+
+        DDF marshall() const {
+            DDF ddf = Attribute::marshall();
+            ddf.name("XML");
+            DDF vlist = ddf.first();
+            for (std::vector<std::string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
+                vlist.add(DDF(NULL).string(i->c_str()));
+            return ddf;
+        }
+
+    private:
+        std::vector<std::string> m_values;
+    };
+
+};
+
+#endif /* __shibsp_xmlattr_h__ */
diff --git a/shibsp/attribute/XMLAttributeDecoder.cpp b/shibsp/attribute/XMLAttributeDecoder.cpp
new file mode 100644 (file)
index 0000000..2d59528
--- /dev/null
@@ -0,0 +1,138 @@
+/*\r
+ *  Copyright 2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * XMLAttributeDecoder.cpp\r
+ *\r
+ * Decodes arbitrary XML into an XMLAttribute.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "attribute/AttributeDecoder.h"\r
+#include "attribute/XMLAttribute.h"\r
+\r
+#include <saml/saml1/core/Assertions.h>\r
+#include <saml/saml2/core/Assertions.h>\r
+#include <xmltooling/util/XMLHelper.h>\r
+\r
+using namespace shibsp;\r
+using namespace opensaml;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+namespace shibsp {\r
+    class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder\r
+    {\r
+    public:\r
+        XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}\r
+        ~XMLAttributeDecoder() {}\r
+\r
+        Attribute* decode(\r
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
+            ) const;\r
+\r
+    private:\r
+        DDF convert(DOMElement* e, bool nameit=true) const;\r
+        auto_ptr_char m_formatter;\r
+        map<pair<xstring,xstring>,string> m_tagMap;\r
+    };\r
+\r
+    AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e)\r
+    {\r
+        return new XMLAttributeDecoder(e);\r
+    }\r
+};\r
+\r
+\r
+Attribute* XMLAttributeDecoder::decode(\r
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
+    ) const\r
+{\r
+    if (!xmlObject)\r
+        return NULL;\r
+\r
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML");\r
+\r
+    auto_ptr<XMLAttribute> attr(new XMLAttribute(ids));\r
+    vector<string>& dest = attr->getValues();\r
+\r
+    // Handle any non-Attribute object directly.\r
+    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
+        DOMElement* e = xmlObject->getDOM();\r
+        if (e) {\r
+            if (log.isDebugEnabled()) {\r
+                log.debug(\r
+                    "decoding XMLAttribute (%s) from XMLObject (%s)",\r
+                    ids.front().c_str(),\r
+                    (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str()\r
+                    );\r
+            }\r
+            dest.push_back(string());\r
+            XMLHelper::serialize(e, dest.back());\r
+        }\r
+        else {\r
+            log.warn("skipping XMLObject without a backing DOM");\r
+        }\r
+        return dest.empty() ? NULL : _decode(attr.release());\r
+    }\r
+\r
+    vector<XMLObject*>::const_iterator v,stop;\r
+\r
+    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
+    if (saml2attr) {\r
+        const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
+        v = values.begin();\r
+        stop = values.end();\r
+        if (log.isDebugEnabled()) {\r
+            auto_ptr_char n(saml2attr->getName());\r
+            log.debug(\r
+                "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
+                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                );\r
+        }\r
+    }\r
+    else {\r
+        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
+        if (saml1attr) {\r
+            const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
+            v = values.begin();\r
+            stop = values.end();\r
+            if (log.isDebugEnabled()) {\r
+                auto_ptr_char n(saml1attr->getAttributeName());\r
+                log.debug(\r
+                    "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
+                    );\r
+            }\r
+        }\r
+        else {\r
+            log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned");\r
+            return NULL;\r
+        }\r
+    }\r
+\r
+    for (; v!=stop; ++v) {\r
+        DOMElement* e = (*v)->getDOM();\r
+        if (e) {\r
+            dest.push_back(string());\r
+            XMLHelper::serialize(e, dest.back());\r
+        }\r
+        else\r
+            log.warn("skipping AttributeValue without a backing DOM");\r
+    }\r
+\r
+    return dest.empty() ? NULL : _decode(attr.release());\r
+}\r
index c8fff06..e465154 100644 (file)
                                        RelativePath=".\attribute\SimpleAttribute.h"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\XMLAttribute.h"\r
+                                       >\r
+                               </File>\r
                        </Filter>\r
                        <Filter\r
                                Name="handler"\r
index a925fe7..cbd630d 100644 (file)
                                        RelativePath=".\attribute\StringAttributeDecoder.cpp"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\XMLAttributeDecoder.cpp"\r
+                                       >\r
+                               </File>\r
                                <Filter\r
                                        Name="resolver"\r
                                        >\r
                                        RelativePath=".\attribute\SimpleAttribute.h"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\XMLAttribute.h"\r
+                                       >\r
+                               </File>\r
                                <Filter\r
                                        Name="resolver"\r
                                        >\r