Make sure groups have names.
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / common / ServiceProviderMapper.java
1 /*
2  * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
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 package edu.internet2.middleware.shibboleth.common;
18
19 import java.net.MalformedURLException;
20 import java.net.URI;
21 import java.net.URISyntaxException;
22 import java.net.URL;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.log4j.Logger;
29 import org.w3c.dom.Element;
30 import org.w3c.dom.NodeList;
31
32 import edu.internet2.middleware.shibboleth.idp.IdPConfig;
33 import edu.internet2.middleware.shibboleth.metadata.EntitiesDescriptor;
34 import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
35 import edu.internet2.middleware.shibboleth.metadata.Metadata;
36
37 /**
38  * Class for determining the effective relying party from the unique id of the service provider. Checks first for an
39  * exact match on the service provider, then for membership in a group of providers (perhaps a federation). Uses the
40  * default relying party if neither is found.
41  * 
42  * @author Walter Hoehn
43  */
44 public class ServiceProviderMapper {
45
46         private static Logger log = Logger.getLogger(ServiceProviderMapper.class.getName());
47         protected Map relyingParties = new HashMap();
48         private Metadata metaData;
49         private IdPConfig configuration;
50         private Credentials credentials;
51         private NameMapper nameMapper;
52
53         public ServiceProviderMapper(Element rawConfig, IdPConfig configuration, Credentials credentials,
54                         NameMapper nameMapper) throws ServiceProviderMapperException {
55
56                 this.configuration = configuration;
57                 this.credentials = credentials;
58                 this.nameMapper = nameMapper;
59
60                 NodeList itemElements = rawConfig.getElementsByTagNameNS(IdPConfig.configNameSpace, "RelyingParty");
61
62                 for (int i = 0; i < itemElements.getLength(); i++) {
63                         addRelyingParty((Element) itemElements.item(i));
64                 }
65
66                 verifyDefaultParty(configuration);
67
68         }
69
70         public void setMetadata(Metadata metadata) {
71
72                 this.metaData = metadata;
73         }
74
75         private IdPConfig getIdPConfig() {
76
77                 return configuration;
78         }
79
80         protected void verifyDefaultParty(IdPConfig configuration) throws ServiceProviderMapperException {
81
82                 // Verify we have a proper default party
83                 String defaultParty = configuration.getDefaultRelyingPartyName();
84                 if (defaultParty == null || defaultParty.equals("")) {
85                         if (relyingParties.size() != 1) {
86                                 log
87                                                 .error("Default Relying Party not specified.  Add a (defaultRelyingParty) attribute to <IdPConfig>.");
88                                 throw new ServiceProviderMapperException("Required configuration not specified.");
89                         } else {
90                                 log.debug("Only one Relying Party loaded.  Using this as the default.");
91                         }
92                 }
93                 log.debug("Default Relying Party set to: (" + defaultParty + ").");
94                 if (!relyingParties.containsKey(defaultParty)) {
95                         log.error("Default Relying Party refers to a Relying Party that has not been loaded.");
96                         throw new ServiceProviderMapperException("Invalid configuration (Default Relying Party).");
97                 }
98         }
99
100         protected RelyingParty getRelyingPartyImpl(String providerIdFromSP) {
101
102                 // Null request, send the default
103                 if (providerIdFromSP == null) {
104                         RelyingParty relyingParty = getDefaultRelyingParty();
105                         log.info("Using default Relying Party: (" + relyingParty.getName() + ").");
106                         return new UnknownProviderWrapper(relyingParty, providerIdFromSP);
107                 }
108
109                 // Look for a configuration for the specific relying party
110                 if (relyingParties.containsKey(providerIdFromSP)) {
111                         log.info("Found Relying Party for (" + providerIdFromSP + ").");
112                         return (RelyingParty) relyingParties.get(providerIdFromSP);
113                 }
114
115                 // Next, check to see if the relying party is in any groups
116                 RelyingParty groupParty = findRelyingPartyByGroup(providerIdFromSP);
117                 if (groupParty != null) {
118                         log.info("Provider is a member of Relying Party (" + groupParty.getName() + ").");
119                         return new RelyingPartyGroupWrapper(groupParty, providerIdFromSP);
120                 }
121
122                 // OK, we can't find it... just send the default
123                 RelyingParty relyingParty = getDefaultRelyingParty();
124                 log.info("Could not locate Relying Party configuration for (" + providerIdFromSP
125                                 + ").  Using default Relying Party: (" + relyingParty.getName() + ").");
126                 return new UnknownProviderWrapper(relyingParty, providerIdFromSP);
127         }
128
129         private RelyingParty findRelyingPartyByGroup(String providerIdFromSP) {
130
131                 if (metaData == null) { return null; }
132
133                 EntityDescriptor provider = metaData.lookup(providerIdFromSP);
134                 if (provider != null) {
135                         EntitiesDescriptor parent = provider.getEntitiesDescriptor();
136                         while (parent != null) {
137                                 if (parent.getName() != null) {
138                                         if (relyingParties.containsKey(parent.getName())) {
139                                                 log.info("Found matching Relying Party for group (" + parent.getName() + ").");
140                                                 return (RelyingParty) relyingParties.get(parent.getName());
141                                         }
142                                         else {
143                                                 log.debug("Provider is a member of group (" + parent.getName()
144                                                                 + "), but no matching Relying Party was found.");
145                                         }
146                                 }
147                                 parent = parent.getEntitiesDescriptor();
148                         }
149                 }
150                 return null;
151         }
152
153         public RelyingParty getDefaultRelyingParty() {
154
155                 // If there is no explicit default, pick the single configured Relying
156                 // Party
157                 String defaultParty = getIdPConfig().getDefaultRelyingPartyName();
158                 if (defaultParty == null || defaultParty.equals("")) { return (RelyingParty) relyingParties.values().iterator()
159                                 .next(); }
160
161                 // If we do have a default specified, use it...
162                 return (RelyingParty) relyingParties.get(defaultParty);
163         }
164
165         /**
166          * Returns the relying party for a legacy provider(the default)
167          */
168         public RelyingParty getLegacyRelyingParty() {
169
170                 RelyingParty relyingParty = getDefaultRelyingParty();
171                 log.info("Request is from legacy shib SP.  Selecting default Relying Party: (" + relyingParty.getName() + ").");
172                 return new LegacyWrapper((RelyingParty) relyingParty);
173
174         }
175
176         /**
177          * Returns the appropriate relying party for the supplied service provider id.
178          */
179         public RelyingParty getRelyingParty(String providerIdFromSP) {
180
181                 if (providerIdFromSP == null || providerIdFromSP.equals("")) {
182                         RelyingParty relyingParty = getDefaultRelyingParty();
183                         log.info("Selecting default Relying Party: (" + relyingParty.getName() + ").");
184                         return new NoMetadataWrapper((RelyingParty) relyingParty);
185                 }
186
187                 return (RelyingParty) getRelyingPartyImpl(providerIdFromSP);
188         }
189
190         private void addRelyingParty(Element e) throws ServiceProviderMapperException {
191
192                 log.debug("Found a Relying Party.");
193                 try {
194                         if (e.getLocalName().equals("RelyingParty")) {
195                                 RelyingParty party = new RelyingPartyImpl(e, configuration, credentials, nameMapper);
196                                 log.debug("Relying Party (" + party.getName() + ") loaded.");
197                                 relyingParties.put(party.getName(), party);
198                         }
199                 } catch (ServiceProviderMapperException exc) {
200                         log.error("Encountered an error while attempting to load Relying Party configuration.  Skipping...");
201                 }
202
203         }
204
205         /**
206          * Base relying party implementation.
207          * 
208          * @author Walter Hoehn
209          */
210         protected class RelyingPartyImpl implements RelyingParty {
211
212                 private RelyingPartyIdentityProvider identityProvider;
213                 private String name;
214                 private String overridenIdPProviderId;
215                 private URL overridenAAUrl;
216                 private URI overridenDefaultAuthMethod;
217                 private List mappingIds = new ArrayList();
218                 private IdPConfig configuration;
219                 private boolean overridenPassThruErrors = false;
220                 private boolean passThruIsOverriden = false;
221                 private boolean forceAttributePush = false;
222                 private boolean forceAttributeNoPush = false;
223                 private boolean defaultToPOST = true;
224                 private boolean wantsAssertionsSigned = false;
225                 private int preferredArtifactType = 1;
226                 private String defaultTarget;
227                 private boolean wantsSchemaHack = false;
228
229                 public RelyingPartyImpl(Element partyConfig, IdPConfig globalConfig, Credentials credentials,
230                                 NameMapper nameMapper) throws ServiceProviderMapperException {
231
232                         configuration = globalConfig;
233
234                         // Get party name
235                         name = ((Element) partyConfig).getAttribute("name");
236                         if (name == null || name.equals("")) {
237                                 log.error("Relying Party name not set.  Add a (name) attribute to <RelyingParty>.");
238                                 throw new ServiceProviderMapperException("Required configuration not specified.");
239                         }
240                         log.debug("Loading Relying Party: (" + name + ").");
241
242                         // Process overrides for global configuration data
243                         String attribute = ((Element) partyConfig).getAttribute("providerId");
244                         if (attribute != null && !attribute.equals("")) {
245                                 log.debug("Overriding providerId for Relying Pary (" + name + ") with (" + attribute + ").");
246                                 overridenIdPProviderId = attribute;
247                         }
248
249                         attribute = ((Element) partyConfig).getAttribute("AAUrl");
250                         if (attribute != null && !attribute.equals("")) {
251                                 log.debug("Overriding AAUrl for Relying Pary (" + name + ") with (" + attribute + ").");
252                                 try {
253                                         overridenAAUrl = new URL(attribute);
254                                 } catch (MalformedURLException e) {
255                                         log.error("(AAUrl) attribute to is not a valid URL.");
256                                         throw new ServiceProviderMapperException("Configuration is invalid.");
257                                 }
258                         }
259
260                         attribute = ((Element) partyConfig).getAttribute("defaultAuthMethod");
261                         if (attribute != null && !attribute.equals("")) {
262                                 log.debug("Overriding defaultAuthMethod for Relying Pary (" + name + ") with (" + attribute + ").");
263                                 try {
264                                         overridenDefaultAuthMethod = new URI(attribute);
265                                 } catch (URISyntaxException e1) {
266                                         log.error("(defaultAuthMethod) attribute to is not a valid URI.");
267                                         throw new ServiceProviderMapperException("Configuration is invalid.");
268                                 }
269                         }
270
271                         attribute = ((Element) partyConfig).getAttribute("passThruErrors");
272                         if (attribute != null && !attribute.equals("")) {
273                                 log.debug("Overriding passThruErrors for Relying Pary (" + name + ") with (" + attribute + ").");
274                                 overridenPassThruErrors = Boolean.valueOf(attribute).booleanValue();
275                                 passThruIsOverriden = true;
276                         }
277
278                         // SSO profile defaulting
279                         attribute = ((Element) partyConfig).getAttribute("defaultToPOSTProfile");
280                         if (attribute != null && !attribute.equals("")) {
281                                 defaultToPOST = Boolean.valueOf(attribute).booleanValue();
282                         }
283                         if (defaultToPOST) {
284                                 log.debug("Relying party defaults to POST profile.");
285                         } else {
286                                 log.debug("Relying party defaults to Artifact profile.");
287                         }
288
289                         // Relying Party wants assertions signed?
290                         attribute = ((Element) partyConfig).getAttribute("signAssertions");
291                         if (attribute != null && !attribute.equals("")) {
292                                 wantsAssertionsSigned = Boolean.valueOf(attribute).booleanValue();
293                         }
294                         if (wantsAssertionsSigned) {
295                                 log.debug("Relying party wants SAML Assertions to be signed.");
296                         } else {
297                                 log.debug("Relying party does not want SAML Assertions to be signed.");
298                         }
299
300                         // Decide whether or not to use the schema hack for old xerces
301                         attribute = ((Element) partyConfig).getAttribute("schemaHack");
302                         if (attribute != null && !attribute.equals("")) {
303                                 wantsSchemaHack = Boolean.valueOf(attribute).booleanValue();
304                         }
305                         if (wantsSchemaHack) {
306                                 log.debug("XML schema hack enabled for this relying party.");
307                         }
308
309                         // Set a default target for use in artifact redirects
310                         defaultTarget = ((Element) partyConfig).getAttribute("defaultTarget");
311
312                         // Determine whether or not we are forcing attribute push on or off
313                         String forcePush = ((Element) partyConfig).getAttribute("forceAttributePush");
314                         String forceNoPush = ((Element) partyConfig).getAttribute("forceAttributeNoPush");
315
316                         if (forcePush != null && Boolean.valueOf(forcePush).booleanValue() && forceNoPush != null
317                                         && Boolean.valueOf(forceNoPush).booleanValue()) {
318                                 log.error("Invalid configuration:  Attribute push is forced to ON and OFF for this relying "
319                                                 + "party.  Turning off forcing in favor of profile defaults.");
320                         } else {
321                                 forceAttributePush = Boolean.valueOf(forcePush).booleanValue();
322                                 forceAttributeNoPush = Boolean.valueOf(forceNoPush).booleanValue();
323                                 log.debug("Attribute push forcing is set to (" + forceAttributePush + ").");
324                                 log.debug("No attribute push forcing is set to (" + forceAttributeNoPush + ").");
325                         }
326
327                         attribute = ((Element) partyConfig).getAttribute("preferredArtifactType");
328                         if (attribute != null && !attribute.equals("")) {
329                                 log.debug("Overriding AAUrl for Relying Pary (" + name + ") with (" + attribute + ").");
330                                 try {
331                                         preferredArtifactType = Integer.parseInt(attribute);
332                                 } catch (NumberFormatException e) {
333                                         log.error("(preferredArtifactType) attribute to is not a valid integer.");
334                                         throw new ServiceProviderMapperException("Configuration is invalid.");
335                                 }
336                                 log.debug("Preferred artifact type: (" + preferredArtifactType + ").");
337                         }
338
339                         // Load and verify the name mappings that should be used in
340                         // assertions for this RelyingParty
341
342                         NodeList nameIDs = ((Element) partyConfig).getElementsByTagNameNS(IdPConfig.configNameSpace, "NameID");
343                         // If no specification. Make sure we have a default mapping
344                         if (nameIDs.getLength() < 1) {
345                                 if (nameMapper.getNameIdentifierMappingById(null) == null) {
346                                         log.error("Relying Party NameId configuration not set.  Add a <NameID> element to <RelyingParty>.");
347                                         throw new ServiceProviderMapperException("Required configuration not specified.");
348                                 }
349
350                         } else {
351
352                                 // We do have a specification, so make sure it points to a
353                                 // valid Name Mapping
354
355                                 for (int i = 0; i < nameIDs.getLength(); i++) {
356
357                                         String mappingId = ((Element) nameIDs.item(i)).getAttribute("nameMapping");
358                                         if (mappingId == null || mappingId.equals("")) {
359                                                 log.error("Name mapping not set.  Add a (nameMapping) attribute to <NameID>.");
360                                                 throw new ServiceProviderMapperException("Required configuration not specified.");
361                                         }
362
363                                         if (nameMapper.getNameIdentifierMappingById(mappingId) == null) {
364                                                 log.error("Relying Party NameID refers to a name mapping that is not loaded.");
365                                                 throw new ServiceProviderMapperException("Required configuration not specified.");
366                                         }
367
368                                         mappingIds.add(mappingId);
369                                 }
370                         }
371
372                         // Load the credential for signing
373                         String credentialName = ((Element) partyConfig).getAttribute("signingCredential");
374                         Credential signingCredential = credentials.getCredential(credentialName);
375                         if (signingCredential == null) {
376                                 if (credentialName == null || credentialName.equals("")) {
377                                         log.error("Relying Party credential not set.  Add a (signingCredential) "
378                                                         + "attribute to <RelyingParty>.");
379                                         throw new ServiceProviderMapperException("Required configuration not specified.");
380                                 } else {
381                                         log.error("Relying Party credential invalid.  Fix the (signingCredential) attribute "
382                                                         + "on <RelyingParty>.");
383                                         throw new ServiceProviderMapperException("Required configuration is invalid.");
384                                 }
385
386                         }
387
388                         // Initialize and Identity Provider object for this use by this relying party
389                         identityProvider = new RelyingPartyIdentityProvider(overridenIdPProviderId != null
390                                         ? overridenIdPProviderId
391                                         : configuration.getProviderId(), signingCredential);
392
393                 }
394
395                 public String getProviderId() {
396
397                         return name;
398                 }
399
400                 public String getName() {
401
402                         return name;
403                 }
404
405                 public IdentityProvider getIdentityProvider() {
406
407                         return identityProvider;
408                 }
409
410                 public boolean isLegacyProvider() {
411
412                         return false;
413                 }
414
415                 public String[] getNameMapperIds() {
416
417                         return (String[]) mappingIds.toArray(new String[0]);
418                 }
419
420                 public URI getDefaultAuthMethod() {
421
422                         if (overridenDefaultAuthMethod != null) {
423                                 return overridenDefaultAuthMethod;
424                         } else {
425                                 return configuration.getDefaultAuthMethod();
426                         }
427                 }
428
429                 public URL getAAUrl() {
430
431                         if (overridenAAUrl != null) {
432                                 return overridenAAUrl;
433                         } else {
434                                 return configuration.getAAUrl();
435                         }
436                 }
437
438                 public boolean passThruErrors() {
439
440                         if (passThruIsOverriden) {
441                                 return overridenPassThruErrors;
442                         } else {
443                                 return configuration.passThruErrors();
444                         }
445                 }
446
447                 public boolean forceAttributePush() {
448
449                         return forceAttributePush;
450                 }
451
452                 public boolean forceAttributeNoPush() {
453
454                         return forceAttributeNoPush;
455                 }
456
457                 public boolean defaultToPOSTProfile() {
458
459                         return defaultToPOST;
460                 }
461
462                 public boolean wantsAssertionsSigned() {
463
464                         return wantsAssertionsSigned;
465                 }
466
467                 public int getPreferredArtifactType() {
468
469                         return preferredArtifactType;
470                 }
471
472                 public String getDefaultTarget() {
473
474                         return defaultTarget;
475                 }
476
477                 public boolean wantsSchemaHack() {
478
479                         return wantsSchemaHack;
480                 }
481
482                 /**
483                  * Default identity provider implementation.
484                  * 
485                  * @author Walter Hoehn
486                  */
487                 protected class RelyingPartyIdentityProvider implements IdentityProvider {
488
489                         private String providerId;
490                         private Credential credential;
491
492                         public RelyingPartyIdentityProvider(String providerId, Credential credential) {
493
494                                 this.providerId = providerId;
495                                 this.credential = credential;
496                         }
497
498                         /*
499                          * @see edu.internet2.middleware.shibboleth.common.IdentityProvider#getProviderId()
500                          */
501                         public String getProviderId() {
502
503                                 return providerId;
504                         }
505
506                         /*
507                          * @see edu.internet2.middleware.shibboleth.common.IdentityProvider#getSigningCredential()
508                          */
509                         public Credential getSigningCredential() {
510
511                                 return credential;
512                         }
513                 }
514
515         }
516
517         /**
518          * Relying party implementation wrapper for relying parties that are groups.
519          * 
520          * @author Walter Hoehn
521          */
522         class RelyingPartyGroupWrapper implements RelyingParty {
523
524                 private RelyingParty wrapped;
525                 private String providerId;
526
527                 RelyingPartyGroupWrapper(RelyingParty wrapped, String providerId) {
528
529                         this.wrapped = wrapped;
530                         this.providerId = providerId;
531                 }
532
533                 public String getName() {
534
535                         return wrapped.getName();
536                 }
537
538                 public boolean isLegacyProvider() {
539
540                         return false;
541                 }
542
543                 public IdentityProvider getIdentityProvider() {
544
545                         return wrapped.getIdentityProvider();
546                 }
547
548                 public String getProviderId() {
549
550                         return providerId;
551                 }
552
553                 public String[] getNameMapperIds() {
554
555                         return wrapped.getNameMapperIds();
556                 }
557
558                 public URL getAAUrl() {
559
560                         return wrapped.getAAUrl();
561                 }
562
563                 public URI getDefaultAuthMethod() {
564
565                         return wrapped.getDefaultAuthMethod();
566                 }
567
568                 public boolean passThruErrors() {
569
570                         return wrapped.passThruErrors();
571                 }
572
573                 public boolean forceAttributePush() {
574
575                         return wrapped.forceAttributePush();
576                 }
577
578                 public boolean forceAttributeNoPush() {
579
580                         return wrapped.forceAttributeNoPush();
581                 }
582
583                 public boolean defaultToPOSTProfile() {
584
585                         return wrapped.defaultToPOSTProfile();
586                 }
587
588                 public boolean wantsAssertionsSigned() {
589
590                         return wrapped.wantsAssertionsSigned();
591                 }
592
593                 public int getPreferredArtifactType() {
594
595                         return wrapped.getPreferredArtifactType();
596                 }
597
598                 public String getDefaultTarget() {
599
600                         return wrapped.getDefaultTarget();
601                 }
602
603                 public boolean wantsSchemaHack() {
604
605                         return wrapped.wantsSchemaHack();
606                 }
607         }
608
609         /**
610          * Relying party implementation wrapper for anonymous service providers.
611          * 
612          * @author Walter Hoehn
613          */
614         protected class UnknownProviderWrapper implements RelyingParty {
615
616                 protected RelyingParty wrapped;
617                 protected String providerId;
618
619                 protected UnknownProviderWrapper(RelyingParty wrapped, String providerId) {
620
621                         this.wrapped = wrapped;
622                         this.providerId = providerId;
623                 }
624
625                 public String getName() {
626
627                         return wrapped.getName();
628                 }
629
630                 public IdentityProvider getIdentityProvider() {
631
632                         return wrapped.getIdentityProvider();
633                 }
634
635                 public String getProviderId() {
636
637                         return providerId;
638                 }
639
640                 public String[] getNameMapperIds() {
641
642                         return wrapped.getNameMapperIds();
643                 }
644
645                 public boolean isLegacyProvider() {
646
647                         return wrapped.isLegacyProvider();
648                 }
649
650                 public URL getAAUrl() {
651
652                         return wrapped.getAAUrl();
653                 }
654
655                 public URI getDefaultAuthMethod() {
656
657                         return wrapped.getDefaultAuthMethod();
658                 }
659
660                 public boolean passThruErrors() {
661
662                         return wrapped.passThruErrors();
663                 }
664
665                 public boolean forceAttributePush() {
666
667                         return false;
668                 }
669
670                 public boolean forceAttributeNoPush() {
671
672                         return false;
673                 }
674
675                 public boolean defaultToPOSTProfile() {
676
677                         return true;
678                 }
679
680                 public boolean wantsAssertionsSigned() {
681
682                         return wrapped.wantsAssertionsSigned();
683                 }
684
685                 public int getPreferredArtifactType() {
686
687                         return wrapped.getPreferredArtifactType();
688                 }
689
690                 public String getDefaultTarget() {
691
692                         return wrapped.getDefaultTarget();
693                 }
694
695                 public boolean wantsSchemaHack() {
696
697                         return wrapped.wantsSchemaHack();
698                 }
699         }
700
701         /**
702          * Relying party wrapper for Shibboleth &lt;=1.1 service providers.
703          * 
704          * @author Walter Hoehn
705          */
706         class LegacyWrapper extends UnknownProviderWrapper implements RelyingParty {
707
708                 LegacyWrapper(RelyingParty wrapped) {
709
710                         super(wrapped, null);
711                 }
712
713                 public boolean isLegacyProvider() {
714
715                         return true;
716                 }
717
718                 public String[] getNameMapperIds() {
719
720                         return ((RelyingParty) wrapped).getNameMapperIds();
721                 }
722
723                 public URL getAAUrl() {
724
725                         return ((RelyingParty) wrapped).getAAUrl();
726                 }
727
728                 public URI getDefaultAuthMethod() {
729
730                         return ((RelyingParty) wrapped).getDefaultAuthMethod();
731                 }
732         }
733
734         /**
735          * Relying party wrapper for providers for which we have no metadata
736          * 
737          * @author Walter Hoehn
738          */
739         class NoMetadataWrapper extends UnknownProviderWrapper implements RelyingParty {
740
741                 NoMetadataWrapper(RelyingParty wrapped) {
742
743                         super(wrapped, null);
744                 }
745
746                 public String[] getNameMapperIds() {
747
748                         return ((RelyingParty) wrapped).getNameMapperIds();
749                 }
750
751                 public URL getAAUrl() {
752
753                         return ((RelyingParty) wrapped).getAAUrl();
754                 }
755
756                 public URI getDefaultAuthMethod() {
757
758                         return ((RelyingParty) wrapped).getDefaultAuthMethod();
759                 }
760         }
761 }