From 3fc853cc1e861f455888a92ff0c9995270d2ba2c Mon Sep 17 00:00:00 2001 From: root Date: Mon, 25 Jul 2011 20:14:02 +0200 Subject: imported 1.1.2 --- .../middleware/shibboleth/wayf/IdPSiteSet.html | 1144 ++++++++++---------- 1 file changed, 580 insertions(+), 564 deletions(-) (limited to 'doc/src-xref/edu/internet2/middleware/shibboleth/wayf/IdPSiteSet.html') diff --git a/doc/src-xref/edu/internet2/middleware/shibboleth/wayf/IdPSiteSet.html b/doc/src-xref/edu/internet2/middleware/shibboleth/wayf/IdPSiteSet.html index acb4888..e77e85a 100644 --- a/doc/src-xref/edu/internet2/middleware/shibboleth/wayf/IdPSiteSet.html +++ b/doc/src-xref/edu/internet2/middleware/shibboleth/wayf/IdPSiteSet.html @@ -1,576 +1,592 @@ - + IdPSiteSet xref
View Javadoc
 
-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  package edu.internet2.middleware.shibboleth.wayf;
-17  
-18  import java.io.File;
-19  import java.lang.reflect.Constructor;
-20  import java.net.MalformedURLException;
-21  import java.net.URL;
-22  import java.util.ArrayList;
-23  import java.util.Collection;
-24  import java.util.Enumeration;
-25  import java.util.HashMap;
-26  import java.util.HashSet;
-27  import java.util.List;
-28  import java.util.Map;
-29  import java.util.Set;
-30  import java.util.StringTokenizer;
-31  import java.util.TreeMap;
-32  
-33  import org.opensaml.saml2.metadata.EntitiesDescriptor;
-34  import org.opensaml.saml2.metadata.EntityDescriptor;
-35  import org.opensaml.saml2.metadata.IDPSSODescriptor;
-36  import org.opensaml.saml2.metadata.Organization;
-37  import org.opensaml.saml2.metadata.OrganizationDisplayName;
-38  import org.opensaml.saml2.metadata.OrganizationName;
-39  import org.opensaml.saml2.metadata.RoleDescriptor;
-40  import org.opensaml.saml2.metadata.SPSSODescriptor;
-41  import org.opensaml.saml2.metadata.provider.FileBackedHTTPMetadataProvider;
-42  import org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider;
-43  import org.opensaml.saml2.metadata.provider.MetadataFilter;
-44  import org.opensaml.saml2.metadata.provider.MetadataFilterChain;
-45  import org.opensaml.saml2.metadata.provider.MetadataProvider;
-46  import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-47  import org.opensaml.saml2.metadata.provider.ObservableMetadataProvider;
-48  import org.opensaml.xml.XMLObject;
-49  import org.opensaml.xml.parse.ParserPool;
-50  import org.slf4j.Logger;
-51  import org.slf4j.LoggerFactory;
-52  import org.w3c.dom.Element;
-53  import org.w3c.dom.NodeList;
-54  
-55  import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
-56  import edu.internet2.middleware.shibboleth.wayf.plugins.Plugin;
-57  import edu.internet2.middleware.shibboleth.wayf.plugins.PluginMetadataParameter;
-58  import edu.internet2.middleware.shibboleth.wayf.plugins.provider.BindingFilter;
-59  
-60  /**
-61   * 
-62   * Represents a collection of related sites as desribed by a single soirce of metadata. 
-63   * This is usually a federation.  When the WAYF looks to see which IdP sites to show, 
-64   * it trims the list so as to not show IdP's which do not trust the SP.
-65   *
-66   * This class is opaque outside this file.  The three static methods getSitesLists,
-67   * searchForMatchingOrigins and lookupIdP provide mechansims for accessing 
-68   * collections of IdPSiteSets.
-69   * 
-70   */
-71  
-72  public class IdPSiteSet implements ObservableMetadataProvider.Observer {
-73          
-74      /** Handle for error output. */
-75      private static final Logger LOG = LoggerFactory.getLogger(IdPSiteSet.class.getName());
-76  
-77      /** The OpenSaml metadata source. */
-78      private ObservableMetadataProvider metadata;
-79  
-80      /** Is the named SP in the current metadata set? */
-81      private Set<String> spNames = new HashSet<String>(0);
-82  
-83      /** Is the named IdP in the current metadata set? */
-84      private Set<String> idpNames = new HashSet<String>(0);
-85      
-86      /** What does the configuration identify this as? */
-87      private final String identifier;
-88      
-89      /** What name should we display for this set of entities? */
-90      private final String displayName;
-91      
-92      /** Where does the metadata exist? */
-93      private String location;
-94      
-95      /** What parameters do we pass in to which plugin? */
-96      private final Map<Plugin, PluginMetadataParameter> plugins = new HashMap<Plugin, PluginMetadataParameter>();
-97      
-98      /**
-99       * Create a new IdPSiteSet as described by the supplied XML segment. 
-100      * @param el - configuration details.
-101      * @param parserPool - the parsers we initialized above.
-102      * @param warnOnBadBinding if we just warn or give an error if an SP has bad entry points.
-103      * @throws ShibbolethConfigurationException - if something goes wrong.
-104      */
-105     protected IdPSiteSet(Element el, ParserPool parserPool, boolean warnOnBadBinding) throws ShibbolethConfigurationException {
-106 
-107         String spoolSpace;
-108         String delayString;
-109 
-110         this.identifier = el.getAttribute("identifier");
-111         this.displayName = el.getAttribute("displayName");
-112         location = el.getAttribute("url");
-113         if (null == location || location.length() == 0) {
-114             //
-115             // Sigh for a few releases this was documented as URI
-116             //
-117             location = el.getAttribute("url");
-118         }
-119         spoolSpace = el.getAttribute("backingFile");
-120         delayString = el.getAttribute("timeout");
-121         
-122         //
-123         // Configure the filters (before the metadata so we can add them before we start reading)
-124         //
-125         String ident;
-126         String className;
-127         ident = "<not specified>"; 
-128         className = "<not specified>"; 
-129         MetadataFilterChain filterChain = null;
-130         filterChain = new MetadataFilterChain();
-131         try {
-132             NodeList itemElements = el.getElementsByTagNameNS(XMLConstants.CONFIG_NS, "Filter");
-133             List <MetadataFilter> filters = new ArrayList<MetadataFilter>(1 + itemElements.getLength());
-134             
-135             //
-136             // We always have a binding filter
-137             //
-138             filters.add(new BindingFilter(warnOnBadBinding));
-139                 
-140             for (int i = 0; i < itemElements.getLength(); i++) {
-141                 Element element = (Element) itemElements.item(i);
-142    
-143                 ident = "<not specified>"; 
-144                 className = "<not specified>"; 
-145             
-146                 ident = element.getAttribute("identifier");
-147 
-148                 if (null == ident || ident.equals("")) {
-149                     LOG.error("Could not load filter with no identifier");
-150                     continue;
-151                 }
-152             
-153                 className = element.getAttribute("type");
-154                 if (null == className || className.equals("")) {
-155                     LOG.error("Filter " + identifier + " did not have a valid type");
-156                 }
-157                 //
-158                 // So try to get hold of the Filter
-159                 //
-160                 Class<MetadataFilter> filterClass = (Class<MetadataFilter>) Class.forName(className);
-161                 Class[] classParams = {Element.class};
-162                 Constructor<MetadataFilter> constructor = filterClass.getConstructor(classParams);
-163                 Object[] constructorParams = {element};
-164             
-165                 filters.add(constructor.newInstance(constructorParams));
-166             }
-167             filterChain.setFilters(filters);
-168         } catch (Exception e) {
-169             LOG.error("Could not load filter " + ident + "()" + className + ") for " + this.identifier, e);
-170             throw new ShibbolethConfigurationException("Could not load filter", e);
-171         }
-172     
-173         LOG.info("Loading Metadata for " + displayName);
-174         try {
-175             int delay;
-176             delay = 30000;
-177             if (null != delayString && !"".equals(delayString)) {
-178                 delay = Integer.parseInt(delayString);
-179             }
-180             
-181             URL url = new URL(location); 
-182             if ("file".equalsIgnoreCase(url.getProtocol())){
-183                 FilesystemMetadataProvider provider = new FilesystemMetadataProvider(new File(url.getFile()));
-184                 provider.setParserPool(parserPool);
-185                 if (null != filterChain) {
-186                     provider.setMetadataFilter(filterChain);
-187                 }
-188                 provider.initialize();
-189                 metadata = provider;
-190             } else {
-191                 if (spoolSpace == null || "".equals(spoolSpace)) {
-192                     throw new ShibbolethConfigurationException("backingFile must be specified for " + identifier);
-193                 }
-194                 
-195                 FileBackedHTTPMetadataProvider provider;
-196             
-197                 provider = new FileBackedHTTPMetadataProvider(location, delay, spoolSpace);
-198                 provider.setParserPool(parserPool);
-199                 if (null != filterChain) {
-200                     provider.setMetadataFilter(filterChain);
-201                 }
-202                 provider.initialize();
-203                 metadata = provider;
-204             }
-205         } catch (MetadataProviderException e) {
-206             throw new ShibbolethConfigurationException("Could not read " + location, e);
-207         } catch (NumberFormatException e) {
-208             throw new ShibbolethConfigurationException("Badly formed timeout " + delayString, e);
-209         } catch (MalformedURLException e) {
-210             throw new ShibbolethConfigurationException("Badly formed url ", e);
-211         }
-212         metadata.getObservers().add(this);
-213         onEvent(metadata);
-214     }
-215 
-216     /**
-217      * Based on 1.2 Origin.isMatch.  There must have been a reason for it...
-218      * [Kindas of] support for the search function in the wayf.  This return many false positives
-219      * but given the aim is to provide input for a pull down list...
-220      * 
-221      * @param entity   The entity to match.
-222      * @param str      The patten to match against.
-223      * @param config   Provides list of tokens to not lookup
-224      * @return         Whether this entity matches  
-225      */
-226 
-227     private static boolean isMatch(EntityDescriptor entity, String str, HandlerConfig config) {
-228         
-229         Enumeration input = new StringTokenizer(str);
-230         while (input.hasMoreElements()) {
-231             String currentToken = (String) input.nextElement();
-232 
-233             if (config.isIgnoredForMatch(currentToken)) {                           
-234                 continue;
-235             }
-236                 
-237             currentToken = currentToken.toLowerCase(); 
-238 
-239             if (entity.getEntityID().indexOf(currentToken) > -1) {
-240                 return true; 
-241             }
-242                                 
-243             Organization org = entity.getOrganization();
-244                 
-245             if (org != null) {
-246                         
-247                 List <OrganizationName> orgNames = org.getOrganizationNames();
-248                 for (OrganizationName name : orgNames) {
-249                     if (name.getName().getLocalString().toLowerCase().indexOf(currentToken) > -1) {
-250                         return true;
-251                     }
-252                 }
-253                         
-254                 List <OrganizationDisplayName> orgDisplayNames = org.getDisplayNames();
-255                 for (OrganizationDisplayName name : orgDisplayNames) {
-256                     if (name.getName().getLocalString().toLowerCase().indexOf(currentToken) > -1) {
-257                         return true;
-258                     }
-259                 }                                
-260             }
-261         }
-262         return false;
-263     }
-264 
-265     /**
-266      * Return all the Idp in the provided entities descriptor.  If SearchMatches
-267      * is non null it is populated with whatever of the IdPs matches the search string 
-268      * (as noted above). 
-269      * @param searchString to match with
-270      * @param config parameter to mathing
-271      * @param searchMatches if non null is filled with such of the sites which match the string
-272      * @return the sites which fit.
-273      */
-274     protected Map<String, IdPSite> getIdPSites(String searchString, 
-275                                                HandlerConfig config, 
-276                                                Collection<IdPSite> searchMatches)
-277     {
-278         XMLObject object;
-279         List <EntityDescriptor> entities;
-280         try {
-281             object = metadata.getMetadata();
-282         } catch (MetadataProviderException e) {
-283             LOG.error("Metadata for " + location + "could not be read", e);
-284             return null;
-285         }
-286         
-287         if (object == null) {
-288             return null;
-289         }
-290         
-291         //
-292         // Fill in entities approptiately
-293         //
-294         
-295         if (object instanceof EntityDescriptor) {
-296             entities = new ArrayList<EntityDescriptor>(1);
-297             entities.add((EntityDescriptor) object);
-298         } else if (object instanceof EntitiesDescriptor) {
-299 
-300             EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) object; 
-301     
-302             entities = entitiesDescriptor.getEntityDescriptors();
-303         } else {
-304            return null;
-305         }
-306        
-307         //
-308         // populate the result (and the searchlist) from the entities list
-309         //
-310         
-311         TreeMap<String, IdPSite> result = new TreeMap <String,IdPSite>();
-312                     
-313         for (EntityDescriptor entity : entities) {
-314                 
-315             if (entity.isValid() && hasIdPRole(entity)) {
-316 
-317                 IdPSite site = new IdPSite(entity);
-318                 result.put(site.getName(), site);
-319                 if (searchMatches != null && isMatch(entity, searchString, config)) {           
-320 
-321                     searchMatches.add(site);
-322                 }
-323 
-324             }
-325         } // iterate over all entities
-326         return result;
-327     }
-328 
-329 
-330     /**
-331      * Return this sites (internal) identifier.
-332      * @return the identifier
-333      */
-334     protected String getIdentifier() {
-335         return identifier;
-336     }
-337 
-338     /**
-339      * Return the human friendly name for this siteset.
-340      * @return The friendly name
-341      */
-342     protected String getDisplayName() {
-343         return displayName;
-344     }
-345 
-346     /**
-347      * We do not need to look at a set if it doesn't know about the given SP.  However if
-348      * no SP is given (as per 1.1) then we do need to look.  This calls lets us know whether 
-349      * this set is a canddiate for looking into.
-350      * @param SPName the Sp we are interested in.
-351      * @return whether the site contains the SP.
-352      */
-353     protected boolean containsSP(String SPName) {
-354 
-355         //
-356         // Deal with the case where we do *not* want to search by
-357         // SP (also handles the 1.1 case)
-358         //
-359         
-360         if ((SPName == null) || (SPName.length() == 0)) {
-361             return true;
-362         }
-363 
-364         //
-365         // Get hold of the current object list so as to provoke observer to fire 
-366         // if needs be.
-367         // 
-368         
-369         XMLObject object;
-370         try {
-371             object = metadata.getMetadata();
-372         } catch (MetadataProviderException e) {
-373             return false;
-374         }
-375         //
-376         // Now lookup
-377         //
-378 
-379         if (object instanceof EntitiesDescriptor ||
-380             object instanceof EntityDescriptor) {
-381             return spNames.contains(SPName);
-382         } else {
-383             return false;
-384         }
-385     }
-386 
-387     /**
-388      * For plugin handling we need to know quickly if a metadataset contains the idp.
-389      * @param IdPName the IdP we are interested in.
-390      * @return whether the site contains the IdP.
-391      * 
-392      */
-393 
-394     protected boolean containsIdP(String IdPName) {
-395         
-396         if ((IdPName == null) || (IdPName.length() == 0)) {
-397             return true;
-398         }
-399 
-400         //
-401         // Get hold of the current object list so as to provoke observer to fire 
-402         // if needs be.
-403         // 
-404         
-405         XMLObject object;
-406         try {
-407             object = metadata.getMetadata();
-408         } catch (MetadataProviderException e) {
-409             return false;
-410         }
-411         if (object instanceof EntitiesDescriptor ||
-412             object instanceof EntityDescriptor) {
-413             return idpNames.contains(IdPName);
-414         } else {
-415             return false;
-416         }
-417     }
-418 
-419     //
-420     // Now deal with plugins - these are delcared to use but we are
-421     // responsible for their parameter
-422     //
-423 
-424     /**
-425      * Declares a plugin to the siteset.
-426      * @param plugin what to declare
-427      */
-428     protected void addPlugin(Plugin plugin) {
-429 
-430         if (plugins.containsKey(plugin)) {
-431             return;
-432         }
-433         
-434         PluginMetadataParameter param = plugin.refreshMetadata(metadata);
-435         
-436         plugins.put(plugin, param);
-437     }
-438 
-439     /**
-440      * Return the parameter that this plugin uses.
-441      * @param plugin
-442      * @return teh parameter.
-443      */
-444     protected PluginMetadataParameter paramFor(Plugin plugin) {
-445         return plugins.get(plugin);
-446     }
-447 
-448 
-449     /* (non-Javadoc)
-450      * @see org.opensaml.saml2.metadata.provider.ObservableMetadataProvider.Observer#onEvent(org.opensaml.saml2.metadata.provider.MetadataProvider)
-451      */
-452     public void onEvent(MetadataProvider provider) {
-453         Set<String> spNameSet = new HashSet<String>(0);
-454         Set<String> idpNameSet = new HashSet<String>(0);
-455 
-456         XMLObject obj; 
-457         try {
-458             obj = provider.getMetadata();
-459         } catch (MetadataProviderException e) {
-460             LOG.error("Couldn't read metadata for " + location, e);
-461             return;
-462         }
-463         if ((obj instanceof EntitiesDescriptor)) {
-464             EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) obj;
-465             
-466             for (EntityDescriptor entity : entitiesDescriptor.getEntityDescriptors()) {
-467                 if (hasSPRole(entity)) {
-468                     spNameSet.add(entity.getEntityID());
-469                 }
-470                 if (hasIdPRole(entity)) {
-471                     idpNameSet.add(entity.getEntityID());
-472                 }
-473             }
-474         } else if (obj instanceof EntityDescriptor) {
-475             EntityDescriptor entity = (EntityDescriptor) obj;
-476             if (hasSPRole(entity)) {
-477                 spNameSet.add(entity.getEntityID());
-478             }
-479             if (hasIdPRole(entity)) {
-480                 idpNameSet.add(entity.getEntityID());
-481             }
-482         } else {
-483             LOG.error("Metadata for " + location + " isn't <EntitiesDescriptor> or <EntityDescriptor>");
-484             return;
-485         }
-486         //
-487         // Now that we have the new set sorted out commit it in
-488         //
-489         this.spNames = spNameSet;
-490         this.idpNames = idpNameSet;
-491         
-492         for (Plugin plugin:plugins.keySet()) {
-493             plugins.put(plugin, plugin.refreshMetadata(provider));
-494         }
-495     }
-496 
-497     /**
-498      * Enumerate all the roles and see whether this entity can be an IdP.
-499      * @param entity
-500      * @return true if one of the roles that entity has is IdPSSO
-501      */
-502     private static boolean hasIdPRole(EntityDescriptor entity) {
-503         List<RoleDescriptor> roles = entity.getRoleDescriptors();
-504         
-505         for (RoleDescriptor role:roles) {
-506            if (role instanceof IDPSSODescriptor) {
-507                //
-508                // So the entity knows how to be some sort of an Idp
-509                //
-510                return true;            
-511            }
-512         }
-513         return false;
-514     }
-515 
-516     /**
-517      * Enumerate all the roles and see whether this entity can be an SP.
-518      * @param entity
-519      * @return true if one of the roles that entity has is SPSSO
-520      */
-521     private static boolean hasSPRole(EntityDescriptor entity) {
-522         List<RoleDescriptor> roles = entity.getRoleDescriptors();
-523         
-524         for (RoleDescriptor role:roles) {
-525            if (role instanceof SPSSODescriptor) {
-526                //
-527                // "I can do that"
-528                //
-529                return true;
-530            }
-531         }
-532         return false;
-533     }
-534 
-535     /**
-536      * Return the idpSite for the given entity name.
-537      * @param idpName the entityname to look up
-538      * @return the associated idpSite
-539      * @throws WayfException
-540      */
-541     protected IdPSite getSite(String idpName) throws WayfException {
-542 
-543         try {
-544             return new IdPSite(metadata.getEntityDescriptor(idpName));
-545         } catch (MetadataProviderException e) {
-546             String s = "Couldn't resolve " + idpName + " in "  + getDisplayName();
-547             LOG.error(s, e);
-548             throw new WayfException(s, e);
-549         }
-550     }
-551     
-552     protected EntityDescriptor getEntity(String name) throws WayfException {
-553         try {
-554             return metadata.getEntityDescriptor(name);
-555         } catch (MetadataProviderException e) {
-556             String s = "Couldn't resolve " + name + " in "  + getDisplayName();
-557             LOG.error(s, e);
-558             throw new WayfException(s, e);
-559         }
-560         
-561     }
-562 }
-563 
+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  package edu.internet2.middleware.shibboleth.wayf;
+17  
+18  import java.io.File;
+19  import java.lang.reflect.Constructor;
+20  import java.net.MalformedURLException;
+21  import java.net.URL;
+22  import java.util.ArrayList;
+23  import java.util.Collection;
+24  import java.util.Enumeration;
+25  import java.util.HashMap;
+26  import java.util.HashSet;
+27  import java.util.List;
+28  import java.util.Map;
+29  import java.util.Set;
+30  import java.util.StringTokenizer;
+31  import java.util.TreeMap;
+32  
+33  import org.opensaml.saml2.metadata.EntitiesDescriptor;
+34  import org.opensaml.saml2.metadata.EntityDescriptor;
+35  import org.opensaml.saml2.metadata.IDPSSODescriptor;
+36  import org.opensaml.saml2.metadata.Organization;
+37  import org.opensaml.saml2.metadata.OrganizationDisplayName;
+38  import org.opensaml.saml2.metadata.OrganizationName;
+39  import org.opensaml.saml2.metadata.RoleDescriptor;
+40  import org.opensaml.saml2.metadata.SPSSODescriptor;
+41  import org.opensaml.saml2.metadata.provider.FileBackedHTTPMetadataProvider;
+42  import org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider;
+43  import org.opensaml.saml2.metadata.provider.MetadataFilter;
+44  import org.opensaml.saml2.metadata.provider.MetadataFilterChain;
+45  import org.opensaml.saml2.metadata.provider.MetadataProvider;
+46  import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+47  import org.opensaml.saml2.metadata.provider.ObservableMetadataProvider;
+48  import org.opensaml.xml.XMLObject;
+49  import org.opensaml.xml.parse.ParserPool;
+50  import org.slf4j.Logger;
+51  import org.slf4j.LoggerFactory;
+52  import org.w3c.dom.Element;
+53  import org.w3c.dom.NodeList;
+54  
+55  import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
+56  import edu.internet2.middleware.shibboleth.wayf.plugins.Plugin;
+57  import edu.internet2.middleware.shibboleth.wayf.plugins.PluginMetadataParameter;
+58  import edu.internet2.middleware.shibboleth.wayf.plugins.provider.BindingFilter;
+59  
+60  /**
+61   * 
+62   * Represents a collection of related sites as described by a single source of metadata. 
+63   * This is usually a federation.  When the WAYF looks to see which IdP sites to show, 
+64   * it trims the list so as to not show IdP's which do not trust the SP.
+65   *
+66   * This class is opaque outside this file.  The three static methods getSitesLists,
+67   * searchForMatchingOrigins and lookupIdP provide mechansims for accessing 
+68   * collections of IdPSiteSets.
+69   * 
+70   */
+71  
+72  public class IdPSiteSet implements ObservableMetadataProvider.Observer {
+73          
+74      /** Handle for error output. */
+75      private static final Logger LOG = LoggerFactory.getLogger(IdPSiteSet.class.getName());
+76  
+77      /** The OpenSaml metadata source. */
+78      private ObservableMetadataProvider metadata;
+79  
+80      /** Is the named SP in the current metadata set? */
+81      private Set<String> spNames = new HashSet<String>(0);
+82  
+83      /** Is the named IdP in the current metadata set? */
+84      private Set<String> idpNames = new HashSet<String>(0);
+85      
+86      /** What does the configuration identify this as? */
+87      private final String identifier;
+88      
+89      /** What name should we display for this set of entities? */
+90      private final String displayName;
+91      
+92      /** Where does the metadata exist? */
+93      private String location;
+94      
+95      /** What parameters do we pass in to which plugin? */
+96      private final Map<Plugin, PluginMetadataParameter> plugins = new HashMap<Plugin, PluginMetadataParameter>();
+97      
+98      /**
+99       * Create a new IdPSiteSet as described by the supplied XML segment. 
+100      * @param el - configuration details.
+101      * @param parserPool - the parsers we initialized above.
+102      * @param warnOnBadBinding if we just warn or give an error if an SP has bad entry points.
+103      * @throws ShibbolethConfigurationException - if something goes wrong.
+104      */
+105     protected IdPSiteSet(Element el, ParserPool parserPool, boolean warnOnBadBinding) throws ShibbolethConfigurationException {
+106 
+107         String spoolSpace;
+108         String delayString;
+109 
+110         this.identifier = el.getAttribute("identifier");
+111         this.displayName = el.getAttribute("displayName");
+112         location = el.getAttribute("url");
+113         if (null == location || location.length() == 0) {
+114             //
+115             // Sigh for a few releases this was documented as URI
+116             //
+117             location = el.getAttribute("url");
+118         }
+119         spoolSpace = el.getAttribute("backingFile");
+120         delayString = el.getAttribute("timeout");
+121         
+122         //
+123         // Configure the filters (before the metadata so we can add them before we start reading)
+124         //
+125         String ident;
+126         String className;
+127         ident = "<not specified>"; 
+128         className = "<not specified>"; 
+129         MetadataFilterChain filterChain = null;
+130         filterChain = new MetadataFilterChain();
+131         try {
+132             NodeList itemElements = el.getElementsByTagNameNS(XMLConstants.CONFIG_NS, "Filter");
+133             List <MetadataFilter> filters = new ArrayList<MetadataFilter>(1 + itemElements.getLength());
+134             
+135             //
+136             // We always have a binding filter
+137             //
+138             filters.add(new BindingFilter(warnOnBadBinding));
+139                 
+140             for (int i = 0; i < itemElements.getLength(); i++) {
+141                 Element element = (Element) itemElements.item(i);
+142    
+143                 ident = "<not specified>"; 
+144                 className = "<not specified>"; 
+145             
+146                 ident = element.getAttribute("identifier");
+147 
+148                 if (null == ident || ident.equals("")) {
+149                     LOG.error("Could not load filter with no identifier");
+150                     continue;
+151                 }
+152             
+153                 className = element.getAttribute("type");
+154                 if (null == className || className.equals("")) {
+155                     LOG.error("Filter " + identifier + " did not have a valid type");
+156                 }
+157                 //
+158                 // So try to get hold of the Filter
+159                 //
+160                 Class<MetadataFilter> filterClass = (Class<MetadataFilter>) Class.forName(className);
+161                 Class[] classParams = {Element.class};
+162                 Constructor<MetadataFilter> constructor = filterClass.getConstructor(classParams);
+163                 Object[] constructorParams = {element};
+164             
+165                 filters.add(constructor.newInstance(constructorParams));
+166             }
+167             filterChain.setFilters(filters);
+168         } catch (Exception e) {
+169             LOG.error("Could not load filter " + ident + "()" + className + ") for " + this.identifier, e);
+170             throw new ShibbolethConfigurationException("Could not load filter", e);
+171         }
+172     
+173         LOG.info("Loading Metadata for " + displayName);
+174         try {
+175             int delay;
+176             delay = 30000;
+177             if (null != delayString && !"".equals(delayString)) {
+178                 delay = Integer.parseInt(delayString);
+179             }
+180             
+181             URL url = new URL(location); 
+182             if ("file".equalsIgnoreCase(url.getProtocol())){
+183                 FilesystemMetadataProvider provider = new FilesystemMetadataProvider(new File(url.getFile()));
+184                 provider.setParserPool(parserPool);
+185                 if (null != filterChain) {
+186                     provider.setMetadataFilter(filterChain);
+187                 }
+188                 provider.initialize();
+189                 metadata = provider;
+190             } else {
+191                 if (spoolSpace == null || "".equals(spoolSpace)) {
+192                     throw new ShibbolethConfigurationException("backingFile must be specified for " + identifier);
+193                 }
+194                 
+195                 FileBackedHTTPMetadataProvider provider;
+196             
+197                 provider = new FileBackedHTTPMetadataProvider(location, delay, spoolSpace);
+198                 provider.setParserPool(parserPool);
+199                 if (null != filterChain) {
+200                     provider.setMetadataFilter(filterChain);
+201                 }
+202                 provider.initialize();
+203                 metadata = provider;
+204             }
+205         } catch (MetadataProviderException e) {
+206             throw new ShibbolethConfigurationException("Could not read " + location, e);
+207         } catch (NumberFormatException e) {
+208             throw new ShibbolethConfigurationException("Badly formed timeout " + delayString, e);
+209         } catch (MalformedURLException e) {
+210             throw new ShibbolethConfigurationException("Badly formed url ", e);
+211         }
+212         metadata.getObservers().add(this);
+213         onEvent(metadata);
+214     }
+215 
+216     /**
+217      * Based on 1.2 Origin.isMatch.  There must have been a reason for it...
+218      * [Kindas of] support for the search function in the wayf.  This return many false positives
+219      * but given the aim is to provide input for a pull down list...
+220      * 
+221      * @param entity   The entity to match.
+222      * @param str      The patten to match against.
+223      * @param config   Provides list of tokens to not lookup
+224      * @return         Whether this entity matches  
+225      */
+226 
+227     private static boolean isMatch(EntityDescriptor entity, String str, HandlerConfig config) {
+228         
+229         Enumeration input = new StringTokenizer(str);
+230         while (input.hasMoreElements()) {
+231             String currentToken = (String) input.nextElement();
+232 
+233             if (config.isIgnoredForMatch(currentToken)) {                           
+234                 continue;
+235             }
+236                 
+237             currentToken = currentToken.toLowerCase(); 
+238 
+239             if (entity.getEntityID().indexOf(currentToken) > -1) {
+240                 return true; 
+241             }
+242                                 
+243             Organization org = entity.getOrganization();
+244                 
+245             if (org != null) {
+246                         
+247                 List <OrganizationName> orgNames = org.getOrganizationNames();
+248                 for (OrganizationName name : orgNames) {
+249                     if (name.getName().getLocalString().toLowerCase().indexOf(currentToken) > -1) {
+250                         return true;
+251                     }
+252                 }
+253                         
+254                 List <OrganizationDisplayName> orgDisplayNames = org.getDisplayNames();
+255                 for (OrganizationDisplayName name : orgDisplayNames) {
+256                     if (name.getName().getLocalString().toLowerCase().indexOf(currentToken) > -1) {
+257                         return true;
+258                     }
+259                 }                                
+260             }
+261         }
+262         return false;
+263     }
+264 
+265     /**
+266      * Return all the Idp in the provided entities descriptor.  If SearchMatches
+267      * is non null it is populated with whatever of the IdPs matches the search string 
+268      * (as noted above). 
+269      * @param searchString to match with
+270      * @param config parameter to mathing
+271      * @param searchMatches if non null is filled with such of the sites which match the string
+272      * @return the sites which fit.
+273      */
+274     protected Map<String, IdPSite> getIdPSites(String searchString, 
+275                                                HandlerConfig config, 
+276                                                Collection<IdPSite> searchMatches)
+277     {
+278         XMLObject object;
+279         List <EntityDescriptor> entities;
+280         try {
+281             object = metadata.getMetadata();
+282         } catch (MetadataProviderException e) {
+283             LOG.error("Metadata for " + location + "could not be read", e);
+284             return null;
+285         }
+286         
+287         if (object == null) {
+288             return null;
+289         }
+290         
+291         //
+292         // Fill in entities approptiately
+293         //
+294         
+295         if (object instanceof EntityDescriptor) {
+296             entities = new ArrayList<EntityDescriptor>(1);
+297             entities.add((EntityDescriptor) object);
+298         } else if (object instanceof EntitiesDescriptor) {
+299 
+300             EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) object; 
+301     
+302             entities = getAllEntities(entitiesDescriptor);
+303         } else {
+304            return null;
+305         }
+306        
+307         //
+308         // populate the result (and the searchlist) from the entities list
+309         //
+310         
+311         TreeMap<String, IdPSite> result = new TreeMap <String,IdPSite>();
+312                     
+313         for (EntityDescriptor entity : entities) {
+314                 
+315             if (entity.isValid() && hasIdPRole(entity)) {
+316 
+317                 IdPSite site = new IdPSite(entity);
+318                 result.put(site.getName(), site);
+319                 if (searchMatches != null && isMatch(entity, searchString, config)) {           
+320 
+321                     searchMatches.add(site);
+322                 }
+323 
+324             }
+325         } // iterate over all entities
+326         return result;
+327     }
+328 
+329 
+330     /**
+331      * Return this sites (internal) identifier.
+332      * @return the identifier
+333      */
+334     protected String getIdentifier() {
+335         return identifier;
+336     }
+337 
+338     /**
+339      * Return the human friendly name for this siteset.
+340      * @return The friendly name
+341      */
+342     protected String getDisplayName() {
+343         return displayName;
+344     }
+345 
+346     /**
+347      * We do not need to look at a set if it doesn't know about the given SP.  However if
+348      * no SP is given (as per 1.1) then we do need to look.  This calls lets us know whether 
+349      * this set is a canddiate for looking into.
+350      * @param SPName the Sp we are interested in.
+351      * @return whether the site contains the SP.
+352      */
+353     protected boolean containsSP(String SPName) {
+354 
+355         //
+356         // Deal with the case where we do *not* want to search by
+357         // SP (also handles the 1.1 case)
+358         //
+359         
+360         if ((SPName == null) || (SPName.length() == 0)) {
+361             return true;
+362         }
+363 
+364         //
+365         // Get hold of the current object list so as to provoke observer to fire 
+366         // if needs be.
+367         // 
+368         
+369         XMLObject object;
+370         try {
+371             object = metadata.getMetadata();
+372         } catch (MetadataProviderException e) {
+373             return false;
+374         }
+375         //
+376         // Now lookup
+377         //
+378 
+379         if (object instanceof EntitiesDescriptor ||
+380             object instanceof EntityDescriptor) {
+381             return spNames.contains(SPName);
+382         } else {
+383             return false;
+384         }
+385     }
+386 
+387     /**
+388      * For plugin handling we need to know quickly if a metadataset contains the idp.
+389      * @param IdPName the IdP we are interested in.
+390      * @return whether the site contains the IdP.
+391      * 
+392      */
+393 
+394     protected boolean containsIdP(String IdPName) {
+395         
+396         if ((IdPName == null) || (IdPName.length() == 0)) {
+397             return true;
+398         }
+399 
+400         //
+401         // Get hold of the current object list so as to provoke observer to fire 
+402         // if needs be.
+403         // 
+404         
+405         XMLObject object;
+406         try {
+407             object = metadata.getMetadata();
+408         } catch (MetadataProviderException e) {
+409             return false;
+410         }
+411         if (object instanceof EntitiesDescriptor ||
+412             object instanceof EntityDescriptor) {
+413             return idpNames.contains(IdPName);
+414         } else {
+415             return false;
+416         }
+417     }
+418 
+419     //
+420     // Now deal with plugins - these are delcared to use but we are
+421     // responsible for their parameter
+422     //
+423 
+424     /**
+425      * Declares a plugin to the siteset.
+426      * @param plugin what to declare
+427      */
+428     protected void addPlugin(Plugin plugin) {
+429 
+430         if (plugins.containsKey(plugin)) {
+431             return;
+432         }
+433         
+434         PluginMetadataParameter param = plugin.refreshMetadata(metadata);
+435         
+436         plugins.put(plugin, param);
+437     }
+438 
+439     /**
+440      * Return the parameter that this plugin uses.
+441      * @param plugin
+442      * @return teh parameter.
+443      */
+444     protected PluginMetadataParameter paramFor(Plugin plugin) {
+445         return plugins.get(plugin);
+446     }
+447 
+448     /**
+449      * Return all the entities below the entities descriptor
+450      * 
+451      * @param entitiesDescriptor the entities descriptor 
+452      * @return
+453      */
+454     
+455     private List<EntityDescriptor> getAllEntities(EntitiesDescriptor entitiesDescriptor)
+456     {
+457         List<EntityDescriptor> result = new ArrayList<EntityDescriptor>(entitiesDescriptor.getEntityDescriptors());
+458         for (EntitiesDescriptor entities : entitiesDescriptor.getEntitiesDescriptors()) {
+459             result.addAll(getAllEntities(entities));
+460         }
+461         return result;
+462     }
+463 
+464     /* (non-Javadoc)
+465      * @see org.opensaml.saml2.metadata.provider.ObservableMetadataProvider.Observer#onEvent(org.opensaml.saml2.metadata.provider.MetadataProvider)
+466      */
+467     
+468     public void onEvent(MetadataProvider provider) {
+469         Set<String> spNameSet = new HashSet<String>(0);
+470         Set<String> idpNameSet = new HashSet<String>(0);
+471 
+472         XMLObject obj; 
+473         try {
+474             obj = provider.getMetadata();
+475         } catch (MetadataProviderException e) {
+476             LOG.error("Couldn't read metadata for " + location, e);
+477             return;
+478         }
+479         if (obj instanceof EntitiesDescriptor) {
+480             EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) obj;
+481             
+482             for (EntityDescriptor entity : getAllEntities(entitiesDescriptor)) {
+483                 if (hasSPRole(entity)) {
+484                     spNameSet.add(entity.getEntityID());
+485                 }
+486                 if (hasIdPRole(entity)) {
+487                     idpNameSet.add(entity.getEntityID());
+488                 }
+489             }
+490         } else if (obj instanceof EntityDescriptor) {
+491             EntityDescriptor entity = (EntityDescriptor) obj;
+492             if (hasSPRole(entity)) {
+493                 spNameSet.add(entity.getEntityID());
+494             }
+495             if (hasIdPRole(entity)) {
+496                 idpNameSet.add(entity.getEntityID());
+497             }
+498         } else {
+499             LOG.error("Metadata for " + location + " isn't <EntitiesDescriptor> or <EntityDescriptor>");
+500             return;
+501         }
+502         //
+503         // Now that we have the new set sorted out commit it in
+504         //
+505         this.spNames = spNameSet;
+506         this.idpNames = idpNameSet;
+507         
+508         for (Plugin plugin:plugins.keySet()) {
+509             plugins.put(plugin, plugin.refreshMetadata(provider));
+510         }
+511     }
+512 
+513     /**
+514      * Enumerate all the roles and see whether this entity can be an IdP.
+515      * @param entity
+516      * @return true if one of the roles that entity has is IdPSSO
+517      */
+518     private static boolean hasIdPRole(EntityDescriptor entity) {
+519         List<RoleDescriptor> roles = entity.getRoleDescriptors();
+520         
+521         for (RoleDescriptor role:roles) {
+522            if (role instanceof IDPSSODescriptor) {
+523                //
+524                // So the entity knows how to be some sort of an Idp
+525                //
+526                return true;            
+527            }
+528         }
+529         return false;
+530     }
+531 
+532     /**
+533      * Enumerate all the roles and see whether this entity can be an SP.
+534      * @param entity
+535      * @return true if one of the roles that entity has is SPSSO
+536      */
+537     private static boolean hasSPRole(EntityDescriptor entity) {
+538         List<RoleDescriptor> roles = entity.getRoleDescriptors();
+539         
+540         for (RoleDescriptor role:roles) {
+541            if (role instanceof SPSSODescriptor) {
+542                //
+543                // "I can do that"
+544                //
+545                return true;
+546            }
+547         }
+548         return false;
+549     }
+550 
+551     /**
+552      * Return the idpSite for the given entity name.
+553      * @param idpName the entityname to look up
+554      * @return the associated idpSite
+555      * @throws WayfException
+556      */
+557     protected IdPSite getSite(String idpName) throws WayfException {
+558 
+559         try {
+560             return new IdPSite(metadata.getEntityDescriptor(idpName));
+561         } catch (MetadataProviderException e) {
+562             String s = "Couldn't resolve " + idpName + " in "  + getDisplayName();
+563             LOG.error(s, e);
+564             throw new WayfException(s, e);
+565         }
+566     }
+567     
+568     protected EntityDescriptor getEntity(String name) throws WayfException {
+569         try {
+570             return metadata.getEntityDescriptor(name);
+571         } catch (MetadataProviderException e) {
+572             String s = "Couldn't resolve " + name + " in "  + getDisplayName();
+573             LOG.error(s, e);
+574             throw new WayfException(s, e);
+575         }
+576         
+577     }
+578 }
+579 
 

-- cgit v1.1