a00e8c76757884382c4ac8d1f5665f697c5c422d
[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 singleAssertion = false;
224                 private boolean defaultToPOST = true;
225                 private boolean wantsAssertionsSigned = false;
226                 private int preferredArtifactType = 1;
227                 private String defaultTarget;
228                 private boolean wantsSchemaHack = false;
229
230                 public RelyingPartyImpl(Element partyConfig, IdPConfig globalConfig, Credentials credentials,
231                                 NameMapper nameMapper) throws ServiceProviderMapperException {
232
233                         configuration = globalConfig;
234
235                         // Get party name
236                         name = ((Element) partyConfig).getAttribute("name");
237                         if (name == null || name.equals("")) {
238                                 log.error("Relying Party name not set.  Add a (name) attribute to <RelyingParty>.");
239                                 throw new ServiceProviderMapperException("Required configuration not specified.");
240                         }
241                         log.debug("Loading Relying Party: (" + name + ").");
242
243                         // Process overrides for global configuration data
244                         String attribute = ((Element) partyConfig).getAttribute("providerId");
245                         if (attribute != null && !attribute.equals("")) {
246                                 log.debug("Overriding providerId for Relying Pary (" + name + ") with (" + attribute + ").");
247                                 overridenIdPProviderId = attribute;
248                         }
249
250                         attribute = ((Element) partyConfig).getAttribute("AAUrl");
251                         if (attribute != null && !attribute.equals("")) {
252                                 log.debug("Overriding AAUrl for Relying Pary (" + name + ") with (" + attribute + ").");
253                                 try {
254                                         overridenAAUrl = new URL(attribute);
255                                 } catch (MalformedURLException e) {
256                                         log.error("(AAUrl) attribute to is not a valid URL.");
257                                         throw new ServiceProviderMapperException("Configuration is invalid.");
258                                 }
259                         }
260
261                         attribute = ((Element) partyConfig).getAttribute("defaultAuthMethod");
262                         if (attribute != null && !attribute.equals("")) {
263                                 log.debug("Overriding defaultAuthMethod for Relying Pary (" + name + ") with (" + attribute + ").");
264                                 try {
265                                         overridenDefaultAuthMethod = new URI(attribute);
266                                 } catch (URISyntaxException e1) {
267                                         log.error("(defaultAuthMethod) attribute to is not a valid URI.");
268                                         throw new ServiceProviderMapperException("Configuration is invalid.");
269                                 }
270                         }
271
272                         attribute = ((Element) partyConfig).getAttribute("passThruErrors");
273                         if (attribute != null && !attribute.equals("")) {
274                                 log.debug("Overriding passThruErrors for Relying Pary (" + name + ") with (" + attribute + ").");
275                                 overridenPassThruErrors = Boolean.valueOf(attribute).booleanValue();
276                                 passThruIsOverriden = true;
277                         }
278
279                         // SSO profile defaulting
280                         attribute = ((Element) partyConfig).getAttribute("defaultToPOSTProfile");
281                         if (attribute != null && !attribute.equals("")) {
282                                 defaultToPOST = Boolean.valueOf(attribute).booleanValue();
283                         }
284                         if (defaultToPOST) {
285                                 log.debug("Relying party defaults to POST profile.");
286                         } else {
287                                 log.debug("Relying party defaults to Artifact profile.");
288                         }
289
290                         // Relying Party wants assertions signed?
291                         attribute = ((Element) partyConfig).getAttribute("signAssertions");
292                         if (attribute != null && !attribute.equals("")) {
293                                 wantsAssertionsSigned = Boolean.valueOf(attribute).booleanValue();
294                         }
295                         if (wantsAssertionsSigned) {
296                                 log.debug("Relying party wants SAML Assertions to be signed.");
297                         } else {
298                                 log.debug("Relying party does not want SAML Assertions to be signed.");
299                         }
300
301                         // Decide whether or not to use the schema hack for old xerces
302                         attribute = ((Element) partyConfig).getAttribute("schemaHack");
303                         if (attribute != null && !attribute.equals("")) {
304                                 wantsSchemaHack = Boolean.valueOf(attribute).booleanValue();
305                         }
306                         if (wantsSchemaHack) {
307                                 log.debug("XML schema hack enabled for this relying party.");
308                         }
309
310                         // Set a default target for use in artifact redirects
311                         defaultTarget = ((Element) partyConfig).getAttribute("defaultTarget");
312
313                         // Determine whether or not we are forcing attribute push on or off
314                         String forcePush = ((Element) partyConfig).getAttribute("forceAttributePush");
315                         String forceNoPush = ((Element) partyConfig).getAttribute("forceAttributeNoPush");
316
317                         if (forcePush != null && Boolean.valueOf(forcePush).booleanValue() && forceNoPush != null
318                                         && Boolean.valueOf(forceNoPush).booleanValue()) {
319                                 log.error("Invalid configuration:  Attribute push is forced to ON and OFF for this relying "
320                                                 + "party.  Turning off forcing in favor of profile defaults.");
321                         } else {
322                                 forceAttributePush = Boolean.valueOf(forcePush).booleanValue();
323                                 forceAttributeNoPush = Boolean.valueOf(forceNoPush).booleanValue();
324                                 log.debug("Attribute push forcing is set to (" + forceAttributePush + ").");
325                                 log.debug("No attribute push forcing is set to (" + forceAttributeNoPush + ").");
326                         }
327
328                         attribute = ((Element) partyConfig).getAttribute("preferredArtifactType");
329                         if (attribute != null && !attribute.equals("")) {
330                                 log.debug("Overriding AAUrl for Relying Pary (" + name + ") with (" + attribute + ").");
331                                 try {
332                                         preferredArtifactType = Integer.parseInt(attribute);
333                                 } catch (NumberFormatException e) {
334                                         log.error("(preferredArtifactType) attribute to is not a valid integer.");
335                                         throw new ServiceProviderMapperException("Configuration is invalid.");
336                                 }
337                                 log.debug("Preferred artifact type: (" + preferredArtifactType + ").");
338                         }
339
340                         // Load and verify the name mappings that should be used in
341                         // assertions for this RelyingParty
342
343                         NodeList nameIDs = ((Element) partyConfig).getElementsByTagNameNS(IdPConfig.configNameSpace, "NameID");
344                         // If no specification. Make sure we have a default mapping
345                         if (nameIDs.getLength() < 1) {
346                                 if (nameMapper.getNameIdentifierMappingById(null) == null) {
347                                         log.error("Relying Party NameId configuration not set.  Add a <NameID> element to <RelyingParty>.");
348                                         throw new ServiceProviderMapperException("Required configuration not specified.");
349                                 }
350
351                         } else {
352
353                                 // We do have a specification, so make sure it points to a
354                                 // valid Name Mapping
355
356                                 for (int i = 0; i < nameIDs.getLength(); i++) {
357
358                                         String mappingId = ((Element) nameIDs.item(i)).getAttribute("nameMapping");
359                                         if (mappingId == null || mappingId.equals("")) {
360                                                 log.error("Name mapping not set.  Add a (nameMapping) attribute to <NameID>.");
361                                                 throw new ServiceProviderMapperException("Required configuration not specified.");
362                                         }
363
364                                         if (nameMapper.getNameIdentifierMappingById(mappingId) == null) {
365                                                 log.error("Relying Party NameID refers to a name mapping that is not loaded.");
366                                                 throw new ServiceProviderMapperException("Required configuration not specified.");
367                                         }
368
369                                         mappingIds.add(mappingId);
370                                 }
371                         }
372
373                         // Load the credential for signing
374                         String credentialName = ((Element) partyConfig).getAttribute("signingCredential");
375                         Credential signingCredential = credentials.getCredential(credentialName);
376                         if (signingCredential == null) {
377                                 if (credentialName == null || credentialName.equals("")) {
378                                         log.error("Relying Party credential not set.  Add a (signingCredential) "
379                                                         + "attribute to <RelyingParty>.");
380                                         throw new ServiceProviderMapperException("Required configuration not specified.");
381                                 } else {
382                                         log.error("Relying Party credential invalid.  Fix the (signingCredential) attribute "
383                                                         + "on <RelyingParty>.");
384                                         throw new ServiceProviderMapperException("Required configuration is invalid.");
385                                 }
386
387                         }
388
389                         // Initialize and Identity Provider object for this use by this relying party
390                         identityProvider = new RelyingPartyIdentityProvider(overridenIdPProviderId != null
391                                         ? overridenIdPProviderId
392                                         : configuration.getProviderId(), signingCredential);
393
394                 }
395
396                 public String getProviderId() {
397
398                         return name;
399                 }
400
401                 public String getName() {
402
403                         return name;
404                 }
405
406                 public IdentityProvider getIdentityProvider() {
407
408                         return identityProvider;
409                 }
410
411                 public boolean isLegacyProvider() {
412
413                         return false;
414                 }
415
416                 public String[] getNameMapperIds() {
417
418                         return (String[]) mappingIds.toArray(new String[0]);
419                 }
420
421                 public URI getDefaultAuthMethod() {
422
423                         if (overridenDefaultAuthMethod != null) {
424                                 return overridenDefaultAuthMethod;
425                         } else {
426                                 return configuration.getDefaultAuthMethod();
427                         }
428                 }
429
430                 public URL getAAUrl() {
431
432                         if (overridenAAUrl != null) {
433                                 return overridenAAUrl;
434                         } else {
435                                 return configuration.getAAUrl();
436                         }
437                 }
438
439                 public boolean passThruErrors() {
440
441                         if (passThruIsOverriden) {
442                                 return overridenPassThruErrors;
443                         } else {
444                                 return configuration.passThruErrors();
445                         }
446                 }
447
448                 public boolean forceAttributePush() {
449
450                         return forceAttributePush;
451                 }
452
453                 public boolean forceAttributeNoPush() {
454
455                         return forceAttributeNoPush;
456                 }
457
458                 public boolean singleAssertion() {
459                         return singleAssertion;
460                 }
461                 
462                 public boolean defaultToPOSTProfile() {
463
464                         return defaultToPOST;
465                 }
466
467                 public boolean wantsAssertionsSigned() {
468
469                         return wantsAssertionsSigned;
470                 }
471
472                 public int getPreferredArtifactType() {
473
474                         return preferredArtifactType;
475                 }
476
477                 public String getDefaultTarget() {
478
479                         return defaultTarget;
480                 }
481
482                 public boolean wantsSchemaHack() {
483
484                         return wantsSchemaHack;
485                 }
486
487                 /**
488                  * Default identity provider implementation.
489                  * 
490                  * @author Walter Hoehn
491                  */
492                 protected class RelyingPartyIdentityProvider implements IdentityProvider {
493
494                         private String providerId;
495                         private Credential credential;
496
497                         public RelyingPartyIdentityProvider(String providerId, Credential credential) {
498
499                                 this.providerId = providerId;
500                                 this.credential = credential;
501                         }
502
503                         /*
504                          * @see edu.internet2.middleware.shibboleth.common.IdentityProvider#getProviderId()
505                          */
506                         public String getProviderId() {
507
508                                 return providerId;
509                         }
510
511                         /*
512                          * @see edu.internet2.middleware.shibboleth.common.IdentityProvider#getSigningCredential()
513                          */
514                         public Credential getSigningCredential() {
515
516                                 return credential;
517                         }
518                 }
519         }
520
521         /**
522          * Relying party implementation wrapper for relying parties that are groups.
523          * 
524          * @author Walter Hoehn
525          */
526         class RelyingPartyGroupWrapper implements RelyingParty {
527
528                 private RelyingParty wrapped;
529                 private String providerId;
530
531                 RelyingPartyGroupWrapper(RelyingParty wrapped, String providerId) {
532
533                         this.wrapped = wrapped;
534                         this.providerId = providerId;
535                 }
536
537                 public String getName() {
538
539                         return wrapped.getName();
540                 }
541
542                 public boolean isLegacyProvider() {
543
544                         return false;
545                 }
546
547                 public IdentityProvider getIdentityProvider() {
548
549                         return wrapped.getIdentityProvider();
550                 }
551
552                 public String getProviderId() {
553
554                         return providerId;
555                 }
556
557                 public String[] getNameMapperIds() {
558
559                         return wrapped.getNameMapperIds();
560                 }
561
562                 public URL getAAUrl() {
563
564                         return wrapped.getAAUrl();
565                 }
566
567                 public URI getDefaultAuthMethod() {
568
569                         return wrapped.getDefaultAuthMethod();
570                 }
571
572                 public boolean passThruErrors() {
573
574                         return wrapped.passThruErrors();
575                 }
576
577                 public boolean forceAttributePush() {
578
579                         return wrapped.forceAttributePush();
580                 }
581
582                 public boolean forceAttributeNoPush() {
583
584                         return wrapped.forceAttributeNoPush();
585                 }
586
587                 public boolean singleAssertion() {
588                         
589                         return wrapped.singleAssertion();
590                 }
591                 
592                 public boolean defaultToPOSTProfile() {
593
594                         return wrapped.defaultToPOSTProfile();
595                 }
596
597                 public boolean wantsAssertionsSigned() {
598
599                         return wrapped.wantsAssertionsSigned();
600                 }
601
602                 public int getPreferredArtifactType() {
603
604                         return wrapped.getPreferredArtifactType();
605                 }
606
607                 public String getDefaultTarget() {
608
609                         return wrapped.getDefaultTarget();
610                 }
611
612                 public boolean wantsSchemaHack() {
613
614                         return wrapped.wantsSchemaHack();
615                 }
616         }
617
618         /**
619          * Relying party implementation wrapper for anonymous service providers.
620          * 
621          * @author Walter Hoehn
622          */
623         protected class UnknownProviderWrapper implements RelyingParty {
624
625                 protected RelyingParty wrapped;
626                 protected String providerId;
627
628                 protected UnknownProviderWrapper(RelyingParty wrapped, String providerId) {
629
630                         this.wrapped = wrapped;
631                         this.providerId = providerId;
632                 }
633
634                 public String getName() {
635
636                         return wrapped.getName();
637                 }
638
639                 public IdentityProvider getIdentityProvider() {
640
641                         return wrapped.getIdentityProvider();
642                 }
643
644                 public String getProviderId() {
645
646                         return providerId;
647                 }
648
649                 public String[] getNameMapperIds() {
650
651                         return wrapped.getNameMapperIds();
652                 }
653
654                 public boolean isLegacyProvider() {
655
656                         return wrapped.isLegacyProvider();
657                 }
658
659                 public URL getAAUrl() {
660
661                         return wrapped.getAAUrl();
662                 }
663
664                 public URI getDefaultAuthMethod() {
665
666                         return wrapped.getDefaultAuthMethod();
667                 }
668
669                 public boolean passThruErrors() {
670
671                         return wrapped.passThruErrors();
672                 }
673
674                 public boolean forceAttributePush() {
675
676                         return false;
677                 }
678
679                 public boolean forceAttributeNoPush() {
680
681                         return false;
682                 }
683
684                 public boolean singleAssertion() {
685                         
686                         return false;
687                 }
688                 
689                 public boolean defaultToPOSTProfile() {
690
691                         return true;
692                 }
693
694                 public boolean wantsAssertionsSigned() {
695
696                         return wrapped.wantsAssertionsSigned();
697                 }
698
699                 public int getPreferredArtifactType() {
700
701                         return wrapped.getPreferredArtifactType();
702                 }
703
704                 public String getDefaultTarget() {
705
706                         return wrapped.getDefaultTarget();
707                 }
708
709                 public boolean wantsSchemaHack() {
710
711                         return wrapped.wantsSchemaHack();
712                 }
713         }
714
715         /**
716          * Relying party wrapper for Shibboleth &lt;=1.1 service providers.
717          * 
718          * @author Walter Hoehn
719          */
720         class LegacyWrapper extends UnknownProviderWrapper implements RelyingParty {
721
722                 LegacyWrapper(RelyingParty wrapped) {
723
724                         super(wrapped, null);
725                 }
726
727                 public boolean isLegacyProvider() {
728
729                         return true;
730                 }
731
732                 public String[] getNameMapperIds() {
733
734                         return ((RelyingParty) wrapped).getNameMapperIds();
735                 }
736
737                 public URL getAAUrl() {
738
739                         return ((RelyingParty) wrapped).getAAUrl();
740                 }
741
742                 public URI getDefaultAuthMethod() {
743
744                         return ((RelyingParty) wrapped).getDefaultAuthMethod();
745                 }
746         }
747
748         /**
749          * Relying party wrapper for providers for which we have no metadata
750          * 
751          * @author Walter Hoehn
752          */
753         class NoMetadataWrapper extends UnknownProviderWrapper implements RelyingParty {
754
755                 NoMetadataWrapper(RelyingParty wrapped) {
756
757                         super(wrapped, null);
758                 }
759
760                 public String[] getNameMapperIds() {
761
762                         return ((RelyingParty) wrapped).getNameMapperIds();
763                 }
764
765                 public URL getAAUrl() {
766
767                         return ((RelyingParty) wrapped).getAAUrl();
768                 }
769
770                 public URI getDefaultAuthMethod() {
771
772                         return ((RelyingParty) wrapped).getDefaultAuthMethod();
773                 }
774         }
775 }