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