2 * Licensed to the University Corporation for Advanced Internet
3 * Development, Inc. (UCAID) under one or more contributor license
4 * agreements. See the NOTICE file distributed with this work for
5 * additional information regarding copyright ownership.
7 * UCAID licenses this file to you under the Apache License,
8 * Version 2.0 (the "License"); you may not use this file except
9 * in compliance with the License. You may obtain a copy of the
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17 * either express or implied. See the License for the specific
18 * language governing permissions and limitations under the License.
24 * DOM-based property set implementation.
28 #include "util/DOMPropertySet.h"
31 #include <boost/lexical_cast.hpp>
32 #include <xmltooling/util/NDC.h>
33 #include <xmltooling/util/XMLConstants.h>
35 using namespace shibsp;
36 using namespace xmltooling;
37 using namespace xercesc;
38 using namespace boost;
41 PropertySet::PropertySet()
45 PropertySet::~PropertySet()
49 DOMPropertySet::DOMPropertySet() : m_parent(nullptr), m_root(nullptr)
53 DOMPropertySet::~DOMPropertySet()
55 for (map<string,pair<char*,const XMLCh*> >::iterator i = m_map.begin(); i != m_map.end(); ++i)
56 XMLString::release(&(i->second.first));
59 const PropertySet* DOMPropertySet::getParent() const
64 void DOMPropertySet::setParent(const PropertySet* parent)
69 const DOMElement* DOMPropertySet::getElement() const
74 void DOMPropertySet::load(
77 DOMNodeFilter* filter,
78 const std::map<std::string,std::string>* remapper
88 log = &Category::getInstance(SHIBSP_LOGCAT".PropertySet");
90 // Process each attribute as a property.
91 DOMNamedNodeMap* attrs=m_root->getAttributes();
92 for (XMLSize_t i=0; i<attrs->getLength(); i++) {
93 DOMNode* a=attrs->item(i);
94 if (!XMLString::compareString(a->getNamespaceURI(),xmlconstants::XMLNS_NS))
96 char* val=XMLString::transcode(a->getNodeValue());
98 auto_ptr_char ns(a->getNamespaceURI());
99 auto_ptr_char name(a->getLocalName());
100 const char* realname=name.get();
101 map<string,string>::const_iterator remap;
103 remap=remapper->find(realname);
104 if (remap!=remapper->end()) {
105 log->warn("deprecation - remapping property (%s) to (%s)",realname,remap->second.c_str());
106 realname=remap->second.c_str();
110 if (remapper && (remap=remapper->find(ns.get()))!=remapper->end())
111 m_map[string("{") + remap->second.c_str() + '}' + realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
113 m_map[string("{") + ns.get() + '}' + realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
114 log->debug("added property {%s}%s (%s)",ns.get(),realname,val);
117 m_map[realname]=pair<char*,const XMLCh*>(val,a->getNodeValue());
118 log->debug("added property %s (%s)",realname,val);
123 // Process non-excluded elements as nested sets.
124 DOMTreeWalker* walker =
125 static_cast<DOMDocumentTraversal*>(
126 m_root->getOwnerDocument())->createTreeWalker(const_cast<DOMElement*>(m_root),DOMNodeFilter::SHOW_ELEMENT,filter,false
128 e = static_cast<DOMElement*>(walker->firstChild());
130 auto_ptr_char ns(e->getNamespaceURI());
131 auto_ptr_char name(e->getLocalName());
132 const char* realname=name.get();
133 map<string,string>::const_iterator remap;
135 remap = remapper->find(realname);
136 if (remap != remapper->end()) {
137 log->warn("deprecation - remapping nested property set (%s) to (%s)", realname, remap->second.c_str());
138 realname = remap->second.c_str();
143 if (remapper && (remap = remapper->find(ns.get())) != remapper->end())
144 key = string("{") + remap->second.c_str() + '}' + realname;
146 key = string("{") + ns.get() + '}' + realname;
150 if (m_nested.find(key) != m_nested.end())
151 log->warn("load() skipping duplicate property set: %s", key.c_str());
153 boost::shared_ptr<DOMPropertySet> newset(new DOMPropertySet());
154 newset->load(e,log,filter,remapper);
155 m_nested[key] = newset;
156 log->debug("added nested property set: %s", key.c_str());
158 e = static_cast<DOMElement*>(walker->nextSibling());
163 pair<bool,bool> DOMPropertySet::getBool(const char* name, const char* ns) const
165 map< string,pair<char*,const XMLCh*> >::const_iterator i;
168 i=m_map.find(string("{") + ns + '}' + name);
173 return make_pair(true,(!strcmp(i->second.first,"true") || !strcmp(i->second.first,"1")));
175 return m_parent->getBool(name,ns);
176 return make_pair(false,false);
179 pair<bool,const char*> DOMPropertySet::getString(const char* name, const char* ns) const
181 pair<bool,const char*> ret(false,nullptr);
182 map< string,pair<char*,const XMLCh*> >::const_iterator i;
185 i=m_map.find(string("{") + ns + '}' + name);
190 return pair<bool,const char*>(true,i->second.first);
192 return m_parent->getString(name,ns);
193 return pair<bool,const char*>(false,nullptr);
196 pair<bool,const XMLCh*> DOMPropertySet::getXMLString(const char* name, const char* ns) const
198 map< string,pair<char*,const XMLCh*> >::const_iterator i;
201 i=m_map.find(string("{") + ns + '}' + name);
206 return make_pair(true,i->second.second);
208 return m_parent->getXMLString(name,ns);
209 return pair<bool,const XMLCh*>(false,nullptr);
212 pair<bool,unsigned int> DOMPropertySet::getUnsignedInt(const char* name, const char* ns) const
214 map< string,pair<char*,const XMLCh*> >::const_iterator i;
217 i=m_map.find(string("{") + ns + '}' + name);
221 if (i!=m_map.end()) {
223 return pair<bool,unsigned int>(true,lexical_cast<unsigned int>(i->second.first));
225 catch (bad_lexical_cast&) {
226 return pair<bool,unsigned int>(false,0);
230 return m_parent->getUnsignedInt(name,ns);
231 return pair<bool,unsigned int>(false,0);
234 pair<bool,int> DOMPropertySet::getInt(const char* name, const char* ns) const
236 map< string,pair<char*,const XMLCh*> >::const_iterator i;
239 i=m_map.find(string("{") + ns + '}' + name);
244 return pair<bool,int>(true,atoi(i->second.first));
246 return m_parent->getInt(name,ns);
247 return pair<bool,int>(false,0);
250 void DOMPropertySet::getAll(std::map<std::string,const char*>& properties) const
253 m_parent->getAll(properties);
254 for (map< string,pair<char*,const XMLCh*> >::const_iterator i = m_map.begin(); i != m_map.end(); ++i)
255 properties[i->first] = i->second.first;
258 const PropertySet* DOMPropertySet::getPropertySet(const char* name, const char* ns) const
260 map< string,boost::shared_ptr<DOMPropertySet> >::const_iterator i;
263 i = m_nested.find(string("{") + ns + '}' + name);
265 i = m_nested.find(name);
267 return (i != m_nested.end()) ? i->second.get() : (m_parent ? m_parent->getPropertySet(name,ns) : nullptr);
270 bool DOMPropertySet::setProperty(const char* name, const char* val, const char* ns)
272 string propname = ns ? (string("{") + ns + "}" + name) : name;
274 // Erase existing property.
275 if (m_map.count(propname) > 0) {
276 XMLString::release(&m_map[propname].first);
277 m_map.erase(propname);
280 char* dup = XMLString::replicate(val);
281 auto_ptr_XMLCh widedup(val);
282 m_injected.push_back(widedup.get());
283 m_map[propname] = make_pair(dup, m_injected.back().c_str());