https://issues.shibboleth.net/jira/browse/CPPOST-73
authorScott Cantor <cantor.2@osu.edu>
Wed, 22 Feb 2012 17:55:33 +0000 (17:55 +0000)
committerScott Cantor <cantor.2@osu.edu>
Wed, 22 Feb 2012 17:55:33 +0000 (17:55 +0000)
saml/saml2/metadata/impl/EntityAttributesMetadataFilter.cpp [new file with mode: 0644]

diff --git a/saml/saml2/metadata/impl/EntityAttributesMetadataFilter.cpp b/saml/saml2/metadata/impl/EntityAttributesMetadataFilter.cpp
new file mode 100644 (file)
index 0000000..407fd81
--- /dev/null
@@ -0,0 +1,160 @@
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID licenses this file to you 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.
+ */
+
+/**
+ * EntityAttributesMetadataFilter.cpp
+ *
+ * Adds EntityAttributes tags to entities.
+ */
+
+#include "internal.h"
+#include "saml2/metadata/Metadata.h"
+#include "saml2/metadata/MetadataFilter.h"
+
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/casts.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#include <xmltooling/logging.h>
+
+using namespace opensaml::saml2;
+using namespace opensaml::saml2md;
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace boost::lambda;
+using namespace boost;
+using namespace std;
+
+namespace opensaml {
+    namespace saml2md {
+
+        class SAML_DLLLOCAL EntityAttributesMetadataFilter : public MetadataFilter
+        {
+        public:
+            EntityAttributesMetadataFilter(const DOMElement* e);
+            ~EntityAttributesMetadataFilter() {}
+
+            const char* getId() const { return ENTITYATTR_METADATA_FILTER; }
+            void doFilter(XMLObject& xmlObject) const;
+
+        private:
+            void filterEntity(EntityDescriptor& entity) const;
+            void filterGroup(EntitiesDescriptor& entities) const;
+
+            vector< boost::shared_ptr<Attribute> > m_attributes;
+            typedef multimap<xstring,const Attribute*> applymap_t;
+            applymap_t m_applyMap;
+        };
+
+        MetadataFilter* SAML_DLLLOCAL EntityAttributesMetadataFilterFactory(const DOMElement* const & e)
+        {
+            return new EntityAttributesMetadataFilter(e);
+        }
+
+        static const XMLCh Entity[] =   UNICODE_LITERAL_6(E,n,t,i,t,y);
+
+    };
+};
+
+
+EntityAttributesMetadataFilter::EntityAttributesMetadataFilter(const DOMElement* e)
+{
+    // Contains ordered set of Attribute and Entity elements.
+    // We track each Attribute we find, and then consume an Entity by adding.
+    // a mapping from the Entity to every Attribute seen to that point.
+    DOMElement* child = XMLHelper::getFirstChildElement(e);
+    while (child) {
+        if (XMLHelper::isNodeNamed(child, samlconstants::SAML20_NS, Attribute::LOCAL_NAME)) {
+            boost::shared_ptr<XMLObject> obj(AttributeBuilder::buildOneFromElement(child));
+            m_attributes.push_back(boost::shared_dynamic_cast<Attribute>(obj));
+        }
+        else if (XMLString::equals(child->getLocalName(), Entity)) {
+            const XMLCh* eid = child->getTextContent();
+            if (eid && *eid) {
+                for (vector< boost::shared_ptr<Attribute> >::const_iterator a = m_attributes.begin(); a != m_attributes.end(); ++a)
+                    m_applyMap.insert(applymap_t::value_type(eid, a->get()));
+            }
+        }
+        child = XMLHelper::getNextSiblingElement(child);
+    }
+}
+
+void EntityAttributesMetadataFilter::doFilter(XMLObject& xmlObject) const
+{
+    EntitiesDescriptor* group = dynamic_cast<EntitiesDescriptor*>(&xmlObject);
+    if (group) {
+        filterGroup(*group);
+    }
+    else {
+        EntityDescriptor* entity = dynamic_cast<EntityDescriptor*>(&xmlObject);
+        if (entity) {
+            filterEntity(*entity);
+        }
+        else {
+            throw MetadataFilterException(ENTITYATTR_METADATA_FILTER" MetadataFilter was given an improper metadata instance to filter.");
+        }
+    }
+}
+
+void EntityAttributesMetadataFilter::filterGroup(EntitiesDescriptor& entities) const
+{
+    const vector<EntityDescriptor*>& v = const_cast<const EntitiesDescriptor&>(entities).getEntityDescriptors();
+    for_each(
+        make_indirect_iterator(v.begin()), make_indirect_iterator(v.end()),
+        lambda::bind(&EntityAttributesMetadataFilter::filterEntity, this, _1)
+        );
+
+    const vector<EntitiesDescriptor*>& v2 = const_cast<const EntitiesDescriptor&>(entities).getEntitiesDescriptors();
+    for_each(
+        make_indirect_iterator(v2.begin()), make_indirect_iterator(v2.end()),
+        lambda::bind(&EntityAttributesMetadataFilter::filterGroup, this, _1)
+        );
+}
+
+void EntityAttributesMetadataFilter::filterEntity(EntityDescriptor& entity) const
+{
+    if (entity.getEntityID()) {
+        pair<applymap_t::const_iterator,applymap_t::const_iterator> tags = m_applyMap.equal_range(entity.getEntityID());
+        if (tags.first != tags.second) {
+            Extensions* exts = entity.getExtensions();
+            if (!exts) {
+                entity.setExtensions(ExtensionsBuilder::buildExtensions());
+                exts = entity.getExtensions();
+            }
+            EntityAttributes* wrapper = nullptr;
+            const vector<XMLObject*>& children = const_cast<const Extensions*>(exts)->getUnknownXMLObjects();
+            XMLObject* xo = find_if(children, ll_dynamic_cast<EntityAttributes*>(_1) != ((EntityAttributes*)nullptr));
+            if (xo) {
+                wrapper = dynamic_cast<EntityAttributes*>(xo);
+            }
+            else {
+                wrapper = EntityAttributesBuilder::buildEntityAttributes();
+                exts->getUnknownXMLObjects().push_back(wrapper);
+            }
+            VectorOf(Attribute) attrs = wrapper->getAttributes();
+            for (; tags.first != tags.second; ++tags.first) {
+                auto_ptr<Attribute> np(tags.first->second->cloneAttribute());
+                attrs.push_back(np.get());
+                np.release();
+            }
+        }
+    }
+}