58632cbc624a44d26f20d6640376b7086f5b6827
[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                 if (remapper && (remap=remapper->find(ns.get()))!=remapper->end())
76                     m_map[string("{") + remap->second.c_str() + '}' + realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
77                 else
78                     m_map[string("{") + ns.get() + '}' + realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
79                 log.debug("added property {%s}%s (%s)",ns.get(),realname,val);
80             }
81             else {
82                 m_map[realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
83                 log.debug("added property %s (%s)",realname,val);
84             }
85         }
86     }
87     
88     // Process non-excluded elements as nested sets.
89     DOMTreeWalker* walker=
90         static_cast<DOMDocumentTraversal*>(
91             m_root->getOwnerDocument())->createTreeWalker(const_cast<DOMElement*>(m_root),DOMNodeFilter::SHOW_ELEMENT,filter,false
92             );
93     e=static_cast<DOMElement*>(walker->firstChild());
94     while (e) {
95         auto_ptr_char ns(e->getNamespaceURI());
96         auto_ptr_char name(e->getLocalName());
97         const char* realname=name.get();
98         map<string,string>::const_iterator remap;
99         if (remapper) {
100             remap=remapper->find(realname);
101             if (remap!=remapper->end()) {
102                 log.warn("remapping property set (%s) to (%s)",realname,remap->second.c_str());
103                 realname=remap->second.c_str();
104             }
105         }
106         string key;
107         if (ns.get()) {
108             if (remapper && (remap=remapper->find(ns.get()))!=remapper->end())
109                 key=string("{") + remap->second.c_str() + '}' + realname;
110             else
111                 key=string("{") + ns.get() + '}' + realname;
112         }
113         else
114             key=realname;
115         if (m_nested.find(key)!=m_nested.end())
116             log.warn("load() skipping duplicate property set: %s",key.c_str());
117         else {
118             DOMPropertySet* set=new DOMPropertySet();
119             set->load(e,log,filter,remapper);
120             m_nested[key]=set;
121             log.debug("added nested property set: %s",key.c_str());
122         }
123         e=static_cast<DOMElement*>(walker->nextSibling());
124     }
125     walker->release();
126 }
127
128 pair<bool,bool> DOMPropertySet::getBool(const char* name, const char* ns) const
129 {
130     pair<bool,bool> ret(false,false);
131     map<string,pair<char*,const XMLCh*> >::const_iterator i;
132
133     if (ns)
134         i=m_map.find(string("{") + ns + '}' + name);
135     else
136         i=m_map.find(name);
137
138     if (i!=m_map.end()) {
139         ret.first=true;
140         ret.second=(!strcmp(i->second.first,"true") || !strcmp(i->second.first,"1"));
141     }
142     return ret;
143 }
144
145 pair<bool,const char*> DOMPropertySet::getString(const char* name, const char* ns) const
146 {
147     pair<bool,const char*> ret(false,NULL);
148     map<string,pair<char*,const XMLCh*> >::const_iterator i;
149
150     if (ns)
151         i=m_map.find(string("{") + ns + '}' + name);
152     else
153         i=m_map.find(name);
154
155     if (i!=m_map.end()) {
156         ret.first=true;
157         ret.second=i->second.first;
158     }
159     return ret;
160 }
161
162 pair<bool,const XMLCh*> DOMPropertySet::getXMLString(const char* name, const char* ns) const
163 {
164     pair<bool,const XMLCh*> ret(false,NULL);
165     map<string,pair<char*,const XMLCh*> >::const_iterator i;
166
167     if (ns)
168         i=m_map.find(string("{") + ns + '}' + name);
169     else
170         i=m_map.find(name);
171
172     if (i!=m_map.end()) {
173         ret.first=true;
174         ret.second=i->second.second;
175     }
176     return ret;
177 }
178
179 pair<bool,unsigned int> DOMPropertySet::getUnsignedInt(const char* name, const char* ns) const
180 {
181     pair<bool,unsigned int> ret(false,0);
182     map<string,pair<char*,const XMLCh*> >::const_iterator i;
183
184     if (ns)
185         i=m_map.find(string("{") + ns + '}' + name);
186     else
187         i=m_map.find(name);
188
189     if (i!=m_map.end()) {
190         ret.first=true;
191         ret.second=strtol(i->second.first,NULL,10);
192     }
193     return ret;
194 }
195
196 pair<bool,int> DOMPropertySet::getInt(const char* name, const char* ns) const
197 {
198     pair<bool,int> ret(false,0);
199     map<string,pair<char*,const XMLCh*> >::const_iterator i;
200
201     if (ns)
202         i=m_map.find(string("{") + ns + '}' + name);
203     else
204         i=m_map.find(name);
205
206     if (i!=m_map.end()) {
207         ret.first=true;
208         ret.second=atoi(i->second.first);
209     }
210     return ret;
211 }
212
213 const PropertySet* DOMPropertySet::getPropertySet(const char* name, const char* ns) const
214 {
215     map<string,DOMPropertySet*>::const_iterator i;
216
217     if (ns)
218         i=m_nested.find(string("{") + ns + '}' + name);
219     else
220         i=m_nested.find(name);
221
222     return (i!=m_nested.end()) ? i->second : NULL;
223 }