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