https://bugs.internet2.edu/jira/browse/SSPCPP-321
[shibboleth/sp.git] / shibsp / attribute / filtering / impl / ChainingAttributeFilter.cpp
1 /*
2  *  Copyright 2001-2010 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * ChainingAttributeFilter.cpp
19  * 
20  * Chains together multiple AttributeFilter plugins.
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "attribute/filtering/AttributeFilter.h"
26 #include "attribute/filtering/FilteringContext.h"
27
28 #include <xercesc/util/XMLUniDefs.hpp>
29 #include <xmltooling/util/XMLHelper.h>
30
31 using namespace shibsp;
32 using namespace xmltooling;
33 using namespace std;
34
35 namespace shibsp {
36
37     class SHIBSP_DLLLOCAL ChainingAttributeFilter : public AttributeFilter
38     {
39     public:
40         ChainingAttributeFilter(const DOMElement* e);
41         virtual ~ChainingAttributeFilter() {
42             for_each(m_filters.begin(), m_filters.end(), xmltooling::cleanup<AttributeFilter>());
43         }
44         
45         Lockable* lock() {
46             return this;
47         }
48         void unlock() {
49         }
50         
51         void filterAttributes(const FilteringContext& context, vector<Attribute*>& attributes) const {
52             for (vector<AttributeFilter*>::const_iterator i=m_filters.begin(); i!=m_filters.end(); ++i) {
53                 Locker locker(*i);
54                 (*i)->filterAttributes(context, attributes);
55             }
56         }
57
58     private:
59         vector<AttributeFilter*> m_filters;
60     };
61
62     static const XMLCh _AttributeFilter[] = UNICODE_LITERAL_15(A,t,t,r,i,b,u,t,e,F,i,l,t,e,r);
63     static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);
64
65     AttributeFilter* SHIBSP_DLLLOCAL ChainingAttributeFilterFactory(const DOMElement* const & e)
66     {
67         return new ChainingAttributeFilter(e);
68     }
69 };
70
71 ChainingAttributeFilter::ChainingAttributeFilter(const DOMElement* e)
72 {
73     // Load up the chain of handlers.
74     try {
75         e = XMLHelper::getFirstChildElement(e, _AttributeFilter);
76         while (e) {
77             string t(XMLHelper::getAttrString(e, nullptr, _type));
78             if (!t.empty()) {
79                 Category::getInstance(SHIBSP_LOGCAT".AttributeFilter.Chaining").info("building AttributeFilter of type (%s)...", t.c_str());
80                 m_filters.push_back(SPConfig::getConfig().AttributeFilterManager.newPlugin(t.c_str(), e));
81             }
82             e = XMLHelper::getNextSiblingElement(e, _AttributeFilter);
83         }
84     }
85     catch (exception&) {
86         for_each(m_filters.begin(), m_filters.end(), xmltooling::cleanup<AttributeFilter>());
87         throw;
88     }
89     if (m_filters.empty())
90         throw ConfigurationException("Chaining AttributeFilter plugin requires at least one child plugin.");
91 }