c9d2db9d6304470091d92e6a500d0cea91c49abd
[shibboleth/sp.git] / shibsp / util / DOMPropertySet.cpp
1 /*
2  *  Copyright 2001-2007 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  * DOMPropertySet.cpp
19  * 
20  * DOM-based property set implementation.
21  */
22
23 #include "internal.h"
24 #include "util/DOMPropertySet.h"
25
26 #include <algorithm>
27 #include <xmltooling/util/NDC.h>
28 #include <xmltooling/util/XMLConstants.h>
29
30 using namespace shibsp;
31 using namespace xmltooling;
32 using namespace log4cpp;
33 using namespace xercesc;
34 using namespace std;
35
36 DOMPropertySet::~DOMPropertySet()
37 {
38     for (map<string,pair<char*,const XMLCh*> >::iterator i=m_map.begin(); i!=m_map.end(); i++)
39         XMLString::release(&(i->second.first));
40     for_each(m_nested.begin(),m_nested.end(),cleanup_pair<string,DOMPropertySet>());
41 }
42
43 void DOMPropertySet::load(
44     const DOMElement* e,
45     Category& log,
46     DOMNodeFilter* filter,
47     const std::map<std::string,std::string>* remapper
48     )
49 {
50 #ifdef _DEBUG
51     NDC ndc("load");
52 #endif
53     m_root=e;
54
55     // Process each attribute as a property.
56     DOMNamedNodeMap* attrs=m_root->getAttributes();
57     for (XMLSize_t i=0; i<attrs->getLength(); i++) {
58         DOMNode* a=attrs->item(i);
59         if (!XMLString::compareString(a->getNamespaceURI(),xmlconstants::XMLNS_NS))
60             continue;
61         char* val=XMLString::transcode(a->getNodeValue());
62         if (val && *val) {
63             auto_ptr_char ns(a->getNamespaceURI());
64             auto_ptr_char name(a->getLocalName());
65             const char* realname=name.get();
66             map<string,string>::const_iterator remap;
67             if (remapper) {
68                 remap=remapper->find(realname);
69                 if (remap!=remapper->end()) {
70                     log.warn("remapping property (%s) to (%s)",realname,remap->second.c_str());
71                     realname=remap->second.c_str();
72                 }
73             }
74             if (ns.get()) {
75                 remap=remapper->find(ns.get());
76                 if (remap!=remapper->end())
77                     m_map[string("{") + remap->second.c_str() + '}' + realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
78                 else
79                     m_map[string("{") + ns.get() + '}' + realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
80                 log.debug("added property {%s}%s (%s)",ns.get(),realname,val);
81             }
82             else {
83                 m_map[realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
84                 log.debug("added property %s (%s)",realname,val);
85             }
86         }
87     }
88     
89     // Process non-excluded elements as nested sets.
90     DOMTreeWalker* walker=
91         static_cast<DOMDocumentTraversal*>(
92             m_root->getOwnerDocument())->createTreeWalker(const_cast<DOMElement*>(m_root),DOMNodeFilter::SHOW_ELEMENT,filter,false
93             );
94     e=static_cast<DOMElement*>(walker->firstChild());
95     while (e) {
96         auto_ptr_char ns(e->getNamespaceURI());
97         auto_ptr_char name(e->getLocalName());
98         const char* realname=name.get();
99         map<string,string>::const_iterator remap;
100         if (remapper) {
101             remap=remapper->find(realname);
102             if (remap!=remapper->end()) {
103                 log.warn("remapping property set (%s) to (%s)",realname,remap->second.c_str());
104                 realname=remap->second.c_str();
105             }
106         }
107         string key;
108         if (ns.get()) {
109             remap=remapper->find(ns.get());
110             if (remap!=remapper->end())
111                 key=string("{") + remap->second.c_str() + '}' + realname;
112             else
113                 key=string("{") + ns.get() + '}' + realname;
114         }
115         else
116             key=realname;
117         if (m_nested.find(key)!=m_nested.end())
118             log.warn("load() skipping duplicate property set: %s",key.c_str());
119         else {
120             DOMPropertySet* set=new DOMPropertySet();
121             set->load(e,log,filter,remapper);
122             m_nested[key]=set;
123             log.debug("added nested property set: %s",key.c_str());
124         }
125         e=static_cast<DOMElement*>(walker->nextSibling());
126     }
127     walker->release();
128 }
129
130 pair<bool,bool> DOMPropertySet::getBool(const char* name, const char* ns) const
131 {
132     pair<bool,bool> ret(false,false);
133     map<string,pair<char*,const XMLCh*> >::const_iterator i;
134
135     if (ns)
136         i=m_map.find(string("{") + ns + '}' + name);
137     else
138         i=m_map.find(name);
139
140     if (i!=m_map.end()) {
141         ret.first=true;
142         ret.second=(!strcmp(i->second.first,"true") || !strcmp(i->second.first,"1"));
143     }
144     return ret;
145 }
146
147 pair<bool,const char*> DOMPropertySet::getString(const char* name, const char* ns) const
148 {
149     pair<bool,const char*> ret(false,NULL);
150     map<string,pair<char*,const XMLCh*> >::const_iterator i;
151
152     if (ns)
153         i=m_map.find(string("{") + ns + '}' + name);
154     else
155         i=m_map.find(name);
156
157     if (i!=m_map.end()) {
158         ret.first=true;
159         ret.second=i->second.first;
160     }
161     return ret;
162 }
163
164 pair<bool,const XMLCh*> DOMPropertySet::getXMLString(const char* name, const char* ns) const
165 {
166     pair<bool,const XMLCh*> ret(false,NULL);
167     map<string,pair<char*,const XMLCh*> >::const_iterator i;
168
169     if (ns)
170         i=m_map.find(string("{") + ns + '}' + name);
171     else
172         i=m_map.find(name);
173
174     if (i!=m_map.end()) {
175         ret.first=true;
176         ret.second=i->second.second;
177     }
178     return ret;
179 }
180
181 pair<bool,unsigned int> DOMPropertySet::getUnsignedInt(const char* name, const char* ns) const
182 {
183     pair<bool,unsigned int> ret(false,0);
184     map<string,pair<char*,const XMLCh*> >::const_iterator i;
185
186     if (ns)
187         i=m_map.find(string("{") + ns + '}' + name);
188     else
189         i=m_map.find(name);
190
191     if (i!=m_map.end()) {
192         ret.first=true;
193         ret.second=strtol(i->second.first,NULL,10);
194     }
195     return ret;
196 }
197
198 pair<bool,int> DOMPropertySet::getInt(const char* name, const char* ns) const
199 {
200     pair<bool,int> ret(false,0);
201     map<string,pair<char*,const XMLCh*> >::const_iterator i;
202
203     if (ns)
204         i=m_map.find(string("{") + ns + '}' + name);
205     else
206         i=m_map.find(name);
207
208     if (i!=m_map.end()) {
209         ret.first=true;
210         ret.second=atoi(i->second.first);
211     }
212     return ret;
213 }
214
215 const PropertySet* DOMPropertySet::getPropertySet(const char* name, const char* ns) const
216 {
217     map<string,DOMPropertySet*>::const_iterator i;
218
219     if (ns)
220         i=m_nested.find(string("{") + ns + '}' + name);
221     else
222         i=m_nested.find(name);
223
224     return (i!=m_nested.end()) ? i->second : NULL;
225 }