Built in pluggable for FederationProvider XML
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / serviceprovider / XMLMetadataImpl.java
1 /*
2  * XMLMetadataImpl.java
3  * 
4  * Process Shibboleth 1.2 Metadata and present an EntityDescriptor
5  * interface.
6  * 
7  * --------------------
8  * Copyright 2002, 2004 
9  * University Corporation for Advanced Internet Development, Inc. 
10  * All rights reserved
11  * [Thats all we have to say to protect ourselves]
12  * Your permission to use this code is governed by "The Shibboleth License".
13  * A copy may be found at http://shibboleth.internet2.edu/license.html
14  * [Nothing in copyright law requires license text in every file.]
15   */
16 package edu.internet2.middleware.shibboleth.serviceprovider;
17
18 import java.net.URL;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23 import java.util.Stack;
24
25 import org.apache.log4j.Logger;
26 import org.apache.xmlbeans.XmlException;
27 import org.opensaml.SAMLAttributeDesignator;
28 import org.w3c.dom.Node;
29
30 import x0.maceShibboleth1.AuthorityType;
31 import x0.maceShibboleth1.ContactType;
32 import x0.maceShibboleth1.OriginSiteType;
33 import x0.maceShibboleth1.SiteGroupDocument;
34 import x0.maceShibboleth1.SiteGroupType;
35 import edu.internet2.middleware.shibboleth.common.XML;
36 import edu.internet2.middleware.shibboleth.metadata.AttributeAuthorityRole;
37 import edu.internet2.middleware.shibboleth.metadata.ContactPerson;
38 import edu.internet2.middleware.shibboleth.metadata.Endpoint;
39 import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
40 import edu.internet2.middleware.shibboleth.metadata.EntityLocator;
41 import edu.internet2.middleware.shibboleth.metadata.IDPProviderRole;
42 import edu.internet2.middleware.shibboleth.metadata.KeyDescriptor;
43 import edu.internet2.middleware.shibboleth.metadata.Provider;
44 import edu.internet2.middleware.shibboleth.metadata.ProviderRole;
45
46
47 /**
48  * Shibboleth 1.2 XML Metadata support
49  */
50 class XMLMetadataImpl 
51         implements 
52                 EntityLocator /* renamed "Metadata" interface */, 
53                 PluggableConfigurationComponent
54         {
55     
56     private static Logger log = Logger.getLogger(XMLMetadataImpl.class);
57     
58         Map entityDescriptors = new HashMap();
59         
60
61         public void initialize(Node dom) 
62                 throws XmlException {
63             SiteGroupDocument bean = SiteGroupDocument.Factory.parse(dom);
64                 Stack parentgroups = new Stack();
65                 processGroup(bean.getSiteGroup(),parentgroups);
66         }
67         
68         /**
69          * Drill down (recursively) through groups to wrap each
70          * OriginSite in a ProviderImp and index by Name.
71          * 
72          * @param group SiteGroup
73          */
74         private void processGroup(SiteGroupType group, Stack parentgroups) {
75                 parentgroups.push(group.getName());
76                 Object[] parents = parentgroups.toArray();
77                 OriginSiteType[] sites = group.getOriginSiteArray();
78                 for (int i=0;i<sites.length;i++) {
79                         entityDescriptors.put(
80                                 sites[i].getName(),
81                                 new XMLEntityDescriptorImpl(sites[i],parents));
82                 }
83                 SiteGroupType[] subgroups = group.getSiteGroupArray();
84                 for (int i=0;i<subgroups.length;i++) {
85                         processGroup(subgroups[i],parentgroups);
86                 }
87                 parentgroups.pop();
88         }
89
90         /**
91          * implement ...metadata.Metadata.lookup
92          * @param entityId ID of remote site
93          * @return EntityDescriptor cast as Provider to fulfill interface
94          */
95         public Provider lookup(String entityId) {
96                 return (EntityDescriptor) entityDescriptors.get(entityId);
97         }
98         
99         /**
100          * SAML 2 rename of lookup
101          * @param entityId ID of remote site
102          * @return EntityDescriptor of site
103          */
104         public EntityDescriptor getEntityDescriptor(String entityId) {
105                 return (EntityDescriptor) entityDescriptors.get(entityId);
106         }
107
108     /**
109      * implements ...metadata.Provider for XML data
110      * 
111      * <p>An object of this class is constructed for every 
112      * OriginSite in the current Shibboleth configuration, and
113      * for every EntityDescriptor in SAML 2 Metadata. It has 
114      * a Role for the HS (IDP) and AA. Of course, it can also
115      * be used in Origin code to describe Targets.
116      */
117     static private class XMLEntityDescriptorImpl extends EntityDescriptor {
118         
119         OriginSiteType site;  // The real XMLBean object
120         Object[] groups; // Actually array of SiteGroupTypes
121         ProviderRole[] roles = null;            
122         
123         XMLEntityDescriptorImpl(OriginSiteType site, Object [] groups) {
124                 this.site=site;
125                 this.groups=groups;
126                 
127                 ArrayList/*<ProviderRoles>*/ roleArray = new ArrayList();
128                 
129                 /*
130                  * Note: The schema allows for more than one AA or IDP.
131                  * This makes sense in SAML 2.0 where different versions of
132                  * the protocol can be supported by different URL endpoints.
133                  * It is not clear how it would really be used here. This
134                  * code goes through the motions of constructing more than
135                  * one AA or IDP Role object, but in practice the subsequent
136                  * code will only use the first such object it encounters.
137                  */
138                 
139                 AuthorityType[] attributeAuthorityArray = site.getAttributeAuthorityArray();
140                 if (attributeAuthorityArray.length>0) {
141                         AttributeAuthorityRole aarole = 
142                                 new AttributeAuthorityRoleImpl(this,attributeAuthorityArray[0]);
143                         roleArray.add(aarole);
144                 }
145                 AuthorityType[] handleServiceArray = site.getHandleServiceArray();
146                 if (handleServiceArray.length>0) {
147                         IDPProviderRole idprole =
148                                 new IDPProviderRoleImpl(this,handleServiceArray[0]);
149                         roleArray.add(idprole);
150                 }
151                 roles = new ProviderRole[roleArray.size()];
152                 Iterator iterator = roleArray.iterator();
153                 for (int i=0;i<roles.length;i++) {
154                     roles[i]= (ProviderRole) iterator.next();
155                 }
156         }
157         
158         public String getId() {
159                 return site.getName();
160         }
161         
162         public String[] getGroups() {
163                 String [] groupnames = new String[groups.length];
164                 for (int i=0;i<groups.length;i++) {
165                         groupnames[i]=((OriginSiteType)groups[i]).getName();
166                 }
167                 return groupnames;
168         }
169     
170         public ContactPerson[] getContacts() {
171                 ContactType[] contacts = site.getContactArray();
172                 XMLContactPersonImpl[] retarray = new XMLContactPersonImpl[contacts.length];
173                 for (int i=0;i<contacts.length;i++) {
174                         retarray[i]=new XMLContactPersonImpl(contacts[i]);
175                 }
176                 return retarray;
177         }
178     
179         public ProviderRole[] getRoles() {
180                 return roles;
181         }
182     }
183
184     /**
185      * implements ...metadata.ContactPerson for XML data
186      */
187     static private class XMLContactPersonImpl implements ContactPerson {
188         
189         ContactType contact; // Wrapped XMLBean object
190         
191         XMLContactPersonImpl(ContactType contact) {
192                 this.contact=contact;
193         }
194     
195         /*
196          * Dependency: the order of values in the XSD enumeration
197          * must match the order of values defined in the interface.
198          * [If someone objects, we can go back and get the string
199          * matching elseif logic.]
200          */
201         public int getType() {
202                 return contact.getType().intValue();
203         }
204     
205         public String getName() {
206                 return contact.getName();
207         }
208     
209         public String[] getEmails() {
210                 return new String[] {contact.getEmail()};
211         }
212     
213         public String[] getTelephones() {
214                 return null;
215         }
216         
217     }
218
219     /**
220      * implements ...metadata.ProviderRole and Endpoint for XML data
221      * 
222      * Note: In the Origin code, the ProviderRole is
223      * implemented directly by the Provider object 
224      * (because from the Origin the Provider has only
225      * one Role). This is not a generally good idea
226      * and it will not work if we move to SAML 2.0 
227      * Metadata. So might as well clean it up now.
228      */
229     static private class XMLProviderRoleImpl 
230         implements ProviderRole, Endpoint {
231         
232         EntityDescriptor entity;
233         private String name;
234         private String location;
235         
236         XMLProviderRoleImpl(EntityDescriptor entity, AuthorityType a) {
237                 this.entity=entity;
238                 this.name = a.getName();
239                 this.location = a.getLocation();
240         }
241     
242         public Provider getProvider() {
243                 return entity;
244         }
245     
246         public String[] getProtocolSupport() {
247                 return new String[]{XML.SHIB_NS};
248         }
249     
250         public boolean hasSupport(String version) {
251                 if (version.equals(XML.SHIB_NS)) {
252                         return true;
253                 } else {
254                         return false;
255                 }
256         }
257     
258         public ContactPerson[] getContacts() {
259                 return entity.getContacts();
260         }
261     
262         public KeyDescriptor[] getKeyDescriptors() {
263                 return null;
264         }
265     
266         public Endpoint[] getDefaultEndpoints() {
267                 return new Endpoint[] {this};
268         }
269     
270         public URL getErrorURL() {
271                 return null;
272         }
273     
274         public String getBinding() {
275                 return XML.SHIB_NS;
276         }
277     
278         public String getVersion() {
279                 return null;
280         }
281     
282         public String getLocation() {
283                 return location;
284         }
285     
286         public String getResponseLocation() {
287                 return null;
288         }
289     }
290
291     /**
292      * implements ...metadata.Endpoint for XML data
293      * 
294      * <p>For now, the Endpoint just wraps a URL.</p>
295      */
296     static private class XMLEndpointImpl implements Endpoint {
297         
298         private String location;
299         
300         XMLEndpointImpl(String location) {
301                 this.location=location;
302         }
303     
304         public String getBinding() {
305                 return XML.SHIB_NS;
306         }
307     
308         public String getVersion() {
309                 return null;
310         }
311     
312         public String getLocation() {
313                 return location;
314         }
315     
316         public String getResponseLocation() {
317                 return null;
318         }
319         
320     }
321
322     /**
323      * A subtype of generic roles for AttributeAuthority entries.
324      */
325     private static class AttributeAuthorityRoleImpl
326         extends XMLProviderRoleImpl
327         implements AttributeAuthorityRole {
328     
329         public AttributeAuthorityRoleImpl(EntityDescriptor entity, AuthorityType a) {
330                 super(entity, a);
331         }
332     
333         public Endpoint[] getAttributeServices() {
334                 return new Endpoint[] {this};
335         }
336     
337         public SAMLAttributeDesignator[] getAttributeDesignators() {
338                 return null;
339         }
340     }
341
342     /**
343      * A subtype of generic roles for Handle Server entries.
344      */
345     private static class IDPProviderRoleImpl
346         extends XMLProviderRoleImpl
347         implements IDPProviderRole {
348     
349         public IDPProviderRoleImpl(EntityDescriptor entity, AuthorityType a) {
350             super(entity, a);
351         }
352     }
353
354     /**
355      * @return
356      */
357     public String getSchemaPathname() {
358         return null;
359     }
360 }