1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.saml2.metadata.provider;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.List;
24
25 import javax.xml.namespace.QName;
26
27 import org.opensaml.saml2.common.SAML2Helper;
28 import org.opensaml.saml2.metadata.EntitiesDescriptor;
29 import org.opensaml.saml2.metadata.EntityDescriptor;
30 import org.opensaml.saml2.metadata.RoleDescriptor;
31 import org.opensaml.xml.XMLObject;
32 import org.opensaml.xml.io.Unmarshaller;
33 import org.opensaml.xml.io.UnmarshallingException;
34 import org.opensaml.xml.parse.ParserPool;
35 import org.opensaml.xml.util.DatatypeHelper;
36 import org.opensaml.xml.util.XMLHelper;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39 import org.slf4j.helpers.MessageFormatter;
40 import org.w3c.dom.Document;
41
42
43 public abstract class AbstractMetadataProvider extends BaseMetadataProvider {
44
45
46 private final Logger log = LoggerFactory.getLogger(AbstractMetadataProvider.class);
47
48
49 private HashMap<String, EntityDescriptor> indexedDescriptors;
50
51
52 private ParserPool parser;
53
54
55 public AbstractMetadataProvider() {
56 super();
57 indexedDescriptors = new HashMap<String, EntityDescriptor>();
58 }
59
60
61 public EntitiesDescriptor getEntitiesDescriptor(String name) throws MetadataProviderException {
62 if (DatatypeHelper.isEmpty(name)) {
63 return null;
64 }
65
66 XMLObject metadata = getMetadata();
67 if (metadata == null) {
68 log.debug("Metadata document was empty, unable to look for an EntitiesDescriptor with the name {}", name);
69 return null;
70 }
71
72 if (metadata instanceof EntitiesDescriptor) {
73 EntitiesDescriptor descriptor = (EntitiesDescriptor) metadata;
74 return getEntitiesDescriptorByName(name, descriptor);
75 }
76
77 log.debug("Metadata document does not contain an EntitiesDescriptor with the name {}", name);
78 return null;
79 }
80
81
82 public EntityDescriptor getEntityDescriptor(String entityID) throws MetadataProviderException {
83 if (DatatypeHelper.isEmpty(entityID)) {
84 return null;
85 }
86
87 XMLObject metadata = getMetadata();
88 if (metadata == null) {
89 log.debug("Metadata document was empty, unable to look for an EntityDescriptor with the ID {}", entityID);
90 return null;
91 }
92
93 EntityDescriptor descriptor = getEntityDescriptorById(entityID, metadata);
94 if (descriptor == null) {
95 log.debug("Metadata document does not contain an EntityDescriptor with the ID {}", entityID);
96 return null;
97 }
98 return descriptor;
99 }
100
101
102 public List<RoleDescriptor> getRole(String entityID, QName roleName) throws MetadataProviderException {
103 if (DatatypeHelper.isEmpty(entityID) || roleName == null) {
104 return null;
105 }
106
107 EntityDescriptor entity = getEntityDescriptor(entityID);
108 if (entity != null) {
109 return entity.getRoleDescriptors(roleName);
110 } else {
111 return null;
112 }
113 }
114
115
116 public RoleDescriptor getRole(String entityID, QName roleName, String supportedProtocol)
117 throws MetadataProviderException {
118 if (DatatypeHelper.isEmpty(entityID) || roleName == null || DatatypeHelper.isEmpty(supportedProtocol)) {
119 return null;
120 }
121
122 List<RoleDescriptor> roles = getRole(entityID, roleName);
123 if (roles == null || roles.isEmpty()) {
124 return null;
125 }
126
127 Iterator<RoleDescriptor> rolesItr = roles.iterator();
128 RoleDescriptor role;
129 while (rolesItr.hasNext()) {
130 role = rolesItr.next();
131 if (role != null && role.isSupportedProtocol(supportedProtocol)) {
132 return role;
133 }
134 }
135
136 return null;
137 }
138
139
140
141
142
143
144 public ParserPool getParserPool() {
145 return parser;
146 }
147
148
149
150
151
152
153 public void setParserPool(ParserPool pool) {
154 parser = pool;
155 }
156
157
158
159
160 protected void clearDescriptorIndex() {
161 indexedDescriptors.clear();
162 }
163
164
165
166
167
168
169
170
171
172
173
174 protected XMLObject unmarshallMetadata(InputStream metadataInput) throws UnmarshallingException {
175 try {
176 log.trace("Parsing retrieved metadata into a DOM object");
177 Document mdDocument = parser.parse(metadataInput);
178
179 log.trace("Unmarshalling and caching metdata DOM");
180 Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(mdDocument.getDocumentElement());
181 if (unmarshaller == null) {
182 String msg = MessageFormatter.format("No unmarshaller registered for document element {}", XMLHelper
183 .getNodeQName(mdDocument.getDocumentElement()));
184 log.error(msg);
185 throw new UnmarshallingException(msg);
186 }
187 XMLObject metadata = unmarshaller.unmarshall(mdDocument.getDocumentElement());
188 return metadata;
189 } catch (Exception e) {
190 throw new UnmarshallingException(e);
191 } finally {
192 try {
193 metadataInput.close();
194 } catch (IOException e) {
195
196 }
197 }
198 }
199
200
201
202
203
204
205
206
207 protected void filterMetadata(XMLObject metadata) throws FilterException {
208 if (getMetadataFilter() != null) {
209 log.debug("Applying metadata filter");
210 getMetadataFilter().doFilter(metadata);
211 }
212 }
213
214
215
216
217
218
219 protected void releaseMetadataDOM(XMLObject metadata) {
220 if (metadata != null) {
221 metadata.releaseDOM();
222 metadata.releaseChildrenDOM(true);
223 }
224 }
225
226
227
228
229
230
231
232
233
234 protected EntityDescriptor getEntityDescriptorById(String entityID, XMLObject metadata) {
235 EntityDescriptor descriptor = null;
236
237 log.debug("Searching for entity descriptor with an entity ID of {}", entityID);
238 if (entityID != null && indexedDescriptors.containsKey(entityID)) {
239 descriptor = indexedDescriptors.get(entityID);
240 if (isValid(descriptor)) {
241 log.trace("Entity descriptor for the ID {} was found in index cache, returning", entityID);
242 return descriptor;
243 } else {
244 indexedDescriptors.remove(descriptor);
245 }
246 }
247
248 if (metadata != null) {
249 if (metadata instanceof EntityDescriptor) {
250 log.trace("Metadata root is an entity descriptor, checking if it's the one we're looking for.");
251 descriptor = (EntityDescriptor) metadata;
252 if (!DatatypeHelper.safeEquals(descriptor.getEntityID(), entityID)) {
253
254 descriptor = null;
255 }
256 if (!isValid(descriptor)) {
257 log.trace("Found entity descriptor for entity with ID {} but it is no longer valid, skipping it.",
258 entityID);
259 descriptor = null;
260 }
261 } else {
262 log
263 .trace("Metadata was an EntitiesDescriptor, checking if any of its descendant EntityDescriptor elements is the one we're looking for.");
264 if (metadata instanceof EntitiesDescriptor) {
265 descriptor = getEntityDescriptorById(entityID, (EntitiesDescriptor) metadata);
266 }
267 }
268 }
269
270 if (descriptor != null) {
271 log.trace("Located entity descriptor, creating an index to it for faster lookups");
272 indexedDescriptors.put(entityID, descriptor);
273 }
274
275 return descriptor;
276 }
277
278
279
280
281
282
283
284
285
286 protected EntityDescriptor getEntityDescriptorById(String entityID, EntitiesDescriptor descriptor) {
287 log.trace("Checking to see if EntitiesDescriptor {} contains the requested descriptor", descriptor.getName());
288 List<EntityDescriptor> entityDescriptors = descriptor.getEntityDescriptors();
289 if (entityDescriptors != null && !entityDescriptors.isEmpty()) {
290 for (EntityDescriptor entityDescriptor : entityDescriptors) {
291 log.trace("Checking entity descriptor with entity ID {}", entityDescriptor.getEntityID());
292 if (DatatypeHelper.safeEquals(entityDescriptor.getEntityID(), entityID) && isValid(entityDescriptor)) {
293 return entityDescriptor;
294 }
295 }
296 }
297
298 log.trace("Checking to see if any of the child entities descriptors contains the entity descriptor requested");
299 EntityDescriptor entityDescriptor;
300 List<EntitiesDescriptor> entitiesDescriptors = descriptor.getEntitiesDescriptors();
301 if (entitiesDescriptors != null && !entitiesDescriptors.isEmpty()) {
302 for (EntitiesDescriptor entitiesDescriptor : descriptor.getEntitiesDescriptors()) {
303 entityDescriptor = getEntityDescriptorById(entityID, entitiesDescriptor);
304 if (entityDescriptor != null) {
305
306
307 return entityDescriptor;
308 }
309 }
310 }
311
312 return null;
313 }
314
315
316
317
318
319
320
321
322
323 protected EntitiesDescriptor getEntitiesDescriptorByName(String name, EntitiesDescriptor rootDescriptor) {
324 EntitiesDescriptor descriptor = null;
325
326 if (DatatypeHelper.safeEquals(name, rootDescriptor.getName()) && isValid(rootDescriptor)) {
327 descriptor = rootDescriptor;
328 } else {
329 List<EntitiesDescriptor> childDescriptors = rootDescriptor.getEntitiesDescriptors();
330 if (childDescriptors == null || childDescriptors.isEmpty()) {
331 return null;
332 }
333 for (EntitiesDescriptor childDescriptor : childDescriptors) {
334 childDescriptor = getEntitiesDescriptorByName(name, childDescriptor);
335 if (childDescriptor != null) {
336 descriptor = childDescriptor;
337 }
338 }
339 }
340
341 return descriptor;
342 }
343
344
345
346
347
348
349
350
351 protected boolean isValid(XMLObject descriptor) {
352 if (descriptor == null) {
353 return false;
354 }
355
356 if (!requireValidMetadata()) {
357 return true;
358 }
359
360 return SAML2Helper.isValid(descriptor);
361 }
362 }