Reducing header overuse, non-inlining selected methods (CPPOST-35).
[shibboleth/cpp-sp.git] / shibsp / attribute / Attribute.cpp
1 /*
2  *  Copyright 2001-2009 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  * shibsp/attribute/Attribute.cpp
19  *
20  * A resolved attribute.
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "SPConfig.h"
26 #ifndef SHIBSP_LITE
27 # include "attribute/AttributeDecoder.h"
28 #endif
29 #include "attribute/SimpleAttribute.h"
30 #include "attribute/ScopedAttribute.h"
31 #include "attribute/NameIDAttribute.h"
32 #include "attribute/ExtensibleAttribute.h"
33 #include "attribute/XMLAttribute.h"
34 #include "util/SPConstants.h"
35
36 #include <xercesc/util/XMLUniDefs.hpp>
37
38 using namespace shibsp;
39 using namespace xmltooling;
40 using namespace std;
41
42 namespace shibsp {
43     SHIBSP_DLLLOCAL Attribute* SimpleAttributeFactory(DDF& in);
44     SHIBSP_DLLLOCAL Attribute* ScopedAttributeFactory(DDF& in);
45     SHIBSP_DLLLOCAL Attribute* NameIDAttributeFactory(DDF& in);
46     SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in);
47     SHIBSP_DLLLOCAL Attribute* XMLAttributeFactory(DDF& in);
48
49 #ifndef SHIBSP_LITE
50     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory StringAttributeDecoderFactory;
51     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory ScopedAttributeDecoderFactory;
52     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory NameIDAttributeDecoderFactory;
53     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory NameIDFromScopedAttributeDecoderFactory;
54     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory KeyInfoAttributeDecoderFactory;
55     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory DOMAttributeDecoderFactory;
56     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory XMLAttributeDecoderFactory;
57
58     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);
59     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);
60     static const XMLCh _NameIDAttributeDecoder[] = UNICODE_LITERAL_22(N,a,m,e,I,D,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
61     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);
62     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);
63     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);
64     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);
65
66     static const XMLCh caseSensitive[] =           UNICODE_LITERAL_13(c,a,s,e,S,e,n,s,i,t,i,v,e);
67     static const XMLCh internal[] =                UNICODE_LITERAL_8(i,n,t,e,r,n,a,l);
68 #endif
69 };
70
71 #ifndef SHIBSP_LITE
72 xmltooling::QName shibsp::StringAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _StringAttributeDecoder);
73 xmltooling::QName shibsp::ScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _ScopedAttributeDecoder);
74 xmltooling::QName shibsp::NameIDAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDAttributeDecoder);
75 xmltooling::QName shibsp::NameIDFromScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDFromScopedAttributeDecoder);
76 xmltooling::QName shibsp::KeyInfoAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _KeyInfoAttributeDecoder);
77 xmltooling::QName shibsp::DOMAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _DOMAttributeDecoder);
78 xmltooling::QName shibsp::XMLAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _XMLAttributeDecoder);
79
80 void shibsp::registerAttributeDecoders()
81 {
82     SPConfig& conf = SPConfig::getConfig();
83     conf.AttributeDecoderManager.registerFactory(StringAttributeDecoderType, StringAttributeDecoderFactory);
84     conf.AttributeDecoderManager.registerFactory(ScopedAttributeDecoderType, ScopedAttributeDecoderFactory);
85     conf.AttributeDecoderManager.registerFactory(NameIDAttributeDecoderType, NameIDAttributeDecoderFactory);
86     conf.AttributeDecoderManager.registerFactory(NameIDFromScopedAttributeDecoderType, NameIDFromScopedAttributeDecoderFactory);
87     conf.AttributeDecoderManager.registerFactory(KeyInfoAttributeDecoderType, KeyInfoAttributeDecoderFactory);
88     conf.AttributeDecoderManager.registerFactory(DOMAttributeDecoderType, DOMAttributeDecoderFactory);
89     conf.AttributeDecoderManager.registerFactory(XMLAttributeDecoderType, XMLAttributeDecoderFactory);
90 }
91
92 AttributeDecoder::AttributeDecoder(const DOMElement *e) : m_caseSensitive(true), m_internal(false)
93 {
94     if (e) {
95         const XMLCh* flag = e->getAttributeNS(NULL, caseSensitive);
96         if (flag && (*flag == chLatin_f || *flag == chDigit_0))
97             m_caseSensitive = false;
98
99         flag = e->getAttributeNS(NULL, internal);
100         if (flag && (*flag == chLatin_t || *flag == chDigit_1))
101             m_internal = true;
102     }
103 }
104
105 AttributeDecoder::~AttributeDecoder()
106 {
107 }
108
109 Attribute* AttributeDecoder::_decode(Attribute* attr) const
110 {
111     attr->setCaseSensitive(m_caseSensitive);
112     attr->setInternal(m_internal);
113     return attr;
114 }
115 #endif
116
117 void shibsp::registerAttributeFactories()
118 {
119     Attribute::registerFactory("", SimpleAttributeFactory);
120     Attribute::registerFactory("Simple", SimpleAttributeFactory);
121     Attribute::registerFactory("Scoped", ScopedAttributeFactory);
122     Attribute::registerFactory("NameID", NameIDAttributeFactory);
123     Attribute::registerFactory("Extensible", ExtensibleAttributeFactory);
124     Attribute::registerFactory("XML", XMLAttributeFactory);
125 }
126
127 map<string,Attribute::AttributeFactory*> Attribute::m_factoryMap;
128
129 void Attribute::registerFactory(const char* type, AttributeFactory* factory)
130 {
131     m_factoryMap[type] = factory;
132 }
133
134 void Attribute::deregisterFactory(const char* type)
135 {
136     m_factoryMap.erase(type);
137 }
138
139 void Attribute::deregisterFactories()
140 {
141     m_factoryMap.clear();
142 }
143
144 Attribute::Attribute(DDF& in) : m_caseSensitive(in["case_insensitive"].isnull()), m_internal(!in["internal"].isnull())
145 {
146     const char* id = in.first().name();
147     if (id && *id)
148         m_id.push_back(id);
149     else
150         throw AttributeException("No id found in marshalled attribute content.");
151     DDF aliases = in["aliases"];
152     if (aliases.islist()) {
153         DDF alias = aliases.first();
154         while (alias.isstring()) {
155             m_id.push_back(alias.string());
156             alias = aliases.next();
157         }
158     }
159 }
160
161 Attribute::~Attribute()
162 {
163 }
164
165 const char* Attribute::getId() const
166 {
167     return m_id.front().c_str();
168 }
169
170 const vector<string>& Attribute::getAliases() const
171 {
172     return m_id;
173 }
174
175 vector<string>& Attribute::getAliases()
176 {
177     return m_id;
178 }
179
180 void Attribute::setCaseSensitive(bool caseSensitive)
181 {
182     m_caseSensitive = caseSensitive;
183 }
184
185 void Attribute::setInternal(bool internal)
186 {
187     m_internal = internal;
188 }
189
190 bool Attribute::isCaseSensitive() const
191 {
192     return m_caseSensitive;
193 }
194
195 bool Attribute::isInternal() const
196 {
197     return m_internal;
198 }
199
200 size_t Attribute::valueCount() const
201 {
202     return m_serialized.size();
203 }
204
205 const vector<string>& Attribute::getSerializedValues() const
206 {
207     return m_serialized;
208 }
209
210 const char* Attribute::getString(size_t index) const
211 {
212     return m_serialized[index].c_str();
213 }
214
215 const char* Attribute::getScope(size_t index) const
216 {
217     return NULL;
218 }
219
220 void Attribute::removeValue(size_t index)
221 {
222     if (index < m_serialized.size())
223         m_serialized.erase(m_serialized.begin() + index);
224 }
225
226 DDF Attribute::marshall() const
227 {
228     DDF ddf(NULL);
229     ddf.structure().addmember(m_id.front().c_str()).list();
230     if (!m_caseSensitive)
231         ddf.addmember("case_insensitive");
232     if (m_internal)
233         ddf.addmember("internal");
234     if (m_id.size() > 1) {
235         DDF alias;
236         DDF aliases = ddf.addmember("aliases").list();
237         for (std::vector<std::string>::const_iterator a = m_id.begin() + 1; a != m_id.end(); ++a) {
238             alias = DDF(NULL).string(a->c_str());
239             aliases.add(alias);
240         }
241     }
242     return ddf;
243 }
244
245 Attribute* Attribute::unmarshall(DDF& in)
246 {
247     map<string,AttributeFactory*>::const_iterator i = m_factoryMap.find(in.name() ? in.name() : "");
248     if (i == m_factoryMap.end())
249         throw AttributeException("No registered factory for Attribute of type ($1).", params(1,in.name()));
250     return (i->second)(in);
251 }