2 * Copyright 2001-2007 Internet2
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * DynamicMetadataProvider.cpp
20 * Base class for caching metadata providers.
24 #include "saml2/metadata/Metadata.h"
25 #include "saml2/metadata/DynamicMetadataProvider.h"
27 #include <xercesc/framework/Wrapper4InputSource.hpp>
\r
28 #include <xercesc/framework/URLInputSource.hpp>
\r
29 #include <xercesc/util/XMLUniDefs.hpp>
\r
30 #include <xmltooling/logging.h>
\r
31 #include <xmltooling/util/XMLHelper.h>
33 using namespace opensaml::saml2md;
34 using namespace xmltooling::logging;
35 using namespace xmltooling;
38 static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
\r
42 MetadataProvider* SAML_DLLLOCAL DynamicMetadataProviderFactory(const DOMElement* const & e)
44 return new DynamicMetadataProvider(e);
49 DynamicMetadataProvider::DynamicMetadataProvider(const DOMElement* e)
50 : AbstractMetadataProvider(e), m_lock(RWLock::create())
52 const XMLCh* flag=e ? e->getAttributeNS(NULL,validate) : NULL;
\r
53 m_validate=(XMLString::equals(flag,xmlconstants::XML_TRUE) || XMLString::equals(flag,xmlconstants::XML_ONE));
\r
56 DynamicMetadataProvider::~DynamicMetadataProvider()
58 // Each entity in the map is unique (no multimap semantics), so this is safe.
59 clearDescriptorIndex(true);
63 const EntityDescriptor* DynamicMetadataProvider::getEntityDescriptor(const char* name, bool strict) const
65 // Check cache while holding the read lock.
66 const EntityDescriptor* entity = AbstractMetadataProvider::getEntityDescriptor(name, strict);
70 Category& log = Category::getInstance(SAML_LOGCAT".MetadataProvider.Dynamic");
71 log.info("resolving metadata for (%s)", name);
74 auto_ptr<EntityDescriptor> entity2(resolve(name));
76 // Filter it, which may throw.
77 doFilters(*entity2.get());
79 log.info("caching resolved metadata for (%s)", name);
81 // Translate cacheDuration into validUntil.
82 if (entity2->getCacheDuration())
83 entity2->setValidUntil(time(NULL) + entity2->getCacheDurationEpoch());
85 // Upgrade our lock so we can cache the new metadata.
92 // Make sure we clear out any existing copies, including stale metadata or if somebody snuck in.
93 index(entity2.release(), SAMLTIME_MAX, true);
95 // Downgrade back to a read lock.
100 return getEntityDescriptor(name, strict);
103 EntityDescriptor* DynamicMetadataProvider::resolve(const char* entityID) const
106 DOMDocument* doc=NULL;
\r
107 auto_ptr_XMLCh widenit(entityID);
\r
108 URLInputSource src(widenit.get());
\r
109 Wrapper4InputSource dsrc(&src,false);
\r
111 doc=XMLToolingConfig::getConfig().getValidatingParser().parse(dsrc);
\r
113 doc=XMLToolingConfig::getConfig().getParser().parse(dsrc);
\r
115 // Wrap the document for now.
116 XercesJanitor<DOMDocument> docjanitor(doc);
118 // Unmarshall objects, binding the document.
119 auto_ptr<XMLObject> xmlObject(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
120 docjanitor.release();
122 // Make sure it's metadata.
123 EntityDescriptor* entity = dynamic_cast<EntityDescriptor*>(xmlObject.get());
125 throw MetadataException(
126 "Root of metadata instance not recognized: $1", params(1,xmlObject->getElementQName().toString().c_str())
129 xmlObject.release();
\r
132 catch (XMLException& e) {
\r
133 auto_ptr_char msg(e.getMessage());
\r
134 Category::getInstance(SAML_LOGCAT".MetadataProvider.Dynamic").error(
\r
135 "Xerces error while resolving entityID (%s): %s", entityID, msg.get()
\r
137 throw MetadataException(msg.get());
\r
139 catch (exception& e) {
\r
140 Category::getInstance(SAML_LOGCAT".MetadataProvider.Dynamic").error(
\r
141 "error while resolving entityID (%s): %s", entityID, e.what()
\r