Shift property set logging to its own category.
[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 xercesc;
33 using namespace std;
34
35 DOMPropertySet::~DOMPropertySet()
36 {
37     for (map<string,pair<char*,const XMLCh*> >::iterator i=m_map.begin(); i!=m_map.end(); i++)
38         XMLString::release(&(i->second.first));
39     for_each(m_nested.begin(),m_nested.end(),cleanup_pair<string,DOMPropertySet>());
40 }
41
42 void DOMPropertySet::load(
43     const DOMElement* e,
44     Category* log,
45     DOMNodeFilter* filter,
46     const std::map<std::string,std::string>* remapper
47     )
48 {
49 #ifdef _DEBUG
50     NDC ndc("load");
51 #endif
52     if (!e)
53         return;
54     m_root=e;
55     if (!log)
56         log = &Category::getInstance(SHIBSP_LOGCAT".PropertySet");
57
58     // Process each attribute as a property.
59     DOMNamedNodeMap* attrs=m_root->getAttributes();
60     for (XMLSize_t i=0; i<attrs->getLength(); i++) {
61         DOMNode* a=attrs->item(i);
62         if (!XMLString::compareString(a->getNamespaceURI(),xmlconstants::XMLNS_NS))
63             continue;
64         char* val=XMLString::transcode(a->getNodeValue());
65         if (val && *val) {
66             auto_ptr_char ns(a->getNamespaceURI());
67             auto_ptr_char name(a->getLocalName());
68             const char* realname=name.get();
69             map<string,string>::const_iterator remap;
70             if (remapper) {
71                 remap=remapper->find(realname);
72                 if (remap!=remapper->end()) {
73                     log->warn("remapping property (%s) to (%s)",realname,remap->second.c_str());
74                     realname=remap->second.c_str();
75                 }
76             }
77             if (ns.get()) {
78                 if (remapper && (remap=remapper->find(ns.get()))!=remapper->end())
79                     m_map[string("{") + remap->second.c_str() + '}' + realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
80                 else
81                     m_map[string("{") + ns.get() + '}' + realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
82                 log->debug("added property {%s}%s (%s)",ns.get(),realname,val);
83             }
84             else {
85                 m_map[realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
86                 log->debug("added property %s (%s)",realname,val);
87             }
88         }
89     }
90     
91     // Process non-excluded elements as nested sets.
92     DOMTreeWalker* walker=
93         static_cast<DOMDocumentTraversal*>(
94             m_root->getOwnerDocument())->createTreeWalker(const_cast<DOMElement*>(m_root),DOMNodeFilter::SHOW_ELEMENT,filter,false
95             );
96     e=static_cast<DOMElement*>(walker->firstChild());
97     while (e) {
98         auto_ptr_char ns(e->getNamespaceURI());
99         auto_ptr_char name(e->getLocalName());
100         const char* realname=name.get();
101         map<string,string>::const_iterator remap;
102         if (remapper) {
103             remap=remapper->find(realname);
104             if (remap!=remapper->end()) {
105                 log->warn("remapping property set (%s) to (%s)",realname,remap->second.c_str());
106                 realname=remap->second.c_str();
107             }
108         }
109         string key;
110         if (ns.get()) {
111             if (remapper && (remap=remapper->find(ns.get()))!=remapper->end())
112                 key=string("{") + remap->second.c_str() + '}' + realname;
113             else
114                 key=string("{") + ns.get() + '}' + realname;
115         }
116         else
117             key=realname;
118         if (m_nested.find(key)!=m_nested.end())
119             log->warn("load() skipping duplicate property set: %s",key.c_str());
120         else {
121             DOMPropertySet* set=new DOMPropertySet();
122             set->load(e,log,filter,remapper);
123             m_nested[key]=set;
124             log->debug("added nested property set: %s",key.c_str());
125         }
126         e=static_cast<DOMElement*>(walker->nextSibling());
127     }
128     walker->release();
129 }
130
131 pair<bool,bool> DOMPropertySet::getBool(const char* name, const char* ns) const
132 {
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         return make_pair(true,(!strcmp(i->second.first,"true") || !strcmp(i->second.first,"1")));
142     else if (m_parent)
143         return m_parent->getBool(name,ns);
144     return make_pair(false,false);
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         return pair<bool,const char*>(true,i->second.first);
159     else if (m_parent)
160         return m_parent->getString(name,ns);
161     return pair<bool,const char*>(false,NULL);
162 }
163
164 pair<bool,const XMLCh*> DOMPropertySet::getXMLString(const char* name, const char* ns) const
165 {
166     map<string,pair<char*,const XMLCh*> >::const_iterator i;
167
168     if (ns)
169         i=m_map.find(string("{") + ns + '}' + name);
170     else
171         i=m_map.find(name);
172
173     if (i!=m_map.end())
174         return make_pair(true,i->second.second);
175     else if (m_parent)
176         return m_parent->getXMLString(name,ns);
177     return pair<bool,const XMLCh*>(false,NULL);
178 }
179
180 pair<bool,unsigned int> DOMPropertySet::getUnsignedInt(const char* name, const char* ns) const
181 {
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         return pair<bool,unsigned int>(true,strtol(i->second.first,NULL,10));
191     else if (m_parent)
192         return m_parent->getUnsignedInt(name,ns);
193     return pair<bool,unsigned int>(false,0);
194 }
195
196 pair<bool,int> DOMPropertySet::getInt(const char* name, const char* ns) const
197 {
198     map<string,pair<char*,const XMLCh*> >::const_iterator i;
199
200     if (ns)
201         i=m_map.find(string("{") + ns + '}' + name);
202     else
203         i=m_map.find(name);
204
205     if (i!=m_map.end())
206         return pair<bool,int>(true,atoi(i->second.first));
207     else if (m_parent)
208         return m_parent->getInt(name,ns);
209     return pair<bool,int>(false,0);
210 }
211
212 void DOMPropertySet::getAll(std::map<std::string,const char*>& properties) const
213 {
214     if (m_parent)
215         m_parent->getAll(properties);
216     for (map< string,pair<char*,const XMLCh*> >::const_iterator i = m_map.begin(); i != m_map.end(); ++i)
217         properties[i->first] = i->second.first;
218 }
219
220 const PropertySet* DOMPropertySet::getPropertySet(const char* name, const char* ns) const
221 {
222     map<string,DOMPropertySet*>::const_iterator i;
223
224     if (ns)
225         i=m_nested.find(string("{") + ns + '}' + name);
226     else
227         i=m_nested.find(name);
228
229     return (i!=m_nested.end()) ? i->second : (m_parent ? m_parent->getPropertySet(name,ns) : NULL);
230 }