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