Wayf changes for new metadata, plus more caching options.
authorcantor <cantor@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Mon, 18 Jul 2005 20:46:36 +0000 (20:46 +0000)
committercantor <cantor@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Mon, 18 Jul 2005 20:46:36 +0000 (20:46 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1728 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/wayf/IdPSite.java [new file with mode: 0644]
src/edu/internet2/middleware/shibboleth/wayf/Origin.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/OriginSet.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/OriginSitesDigester.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/WayfOrigins.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/WayfService.java
webApplication/wayf.jsp

diff --git a/src/edu/internet2/middleware/shibboleth/wayf/IdPSite.java b/src/edu/internet2/middleware/shibboleth/wayf/IdPSite.java
new file mode 100644 (file)
index 0000000..441c6db
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package edu.internet2.middleware.shibboleth.wayf;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+
+import edu.internet2.middleware.shibboleth.metadata.EntitiesDescriptor;
+import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
+import edu.internet2.middleware.shibboleth.metadata.Metadata;
+
+import edu.internet2.middleware.shibboleth.metadata.Organization;
+
+public class IdPSite implements Comparable {
+
+       private final EntityDescriptor entity;
+       
+       public IdPSite(EntityDescriptor entity)
+       {
+               this.entity = entity;
+       }
+       
+       public String getName()
+       {
+               return entity.getId();
+       }
+       
+       public String getDisplayName()
+       {
+               Organization org = entity.getOrganization();
+               
+               if (org == null) {
+                       return entity.getId();
+               }
+               else {
+                       return org.getDisplayName();
+               }
+       }
+
+       /**
+        * Based on 1.2 Origin.isMatch.  There must have been a reason for it...
+        * [Kindas of] support for the search function in the wayf.  This return many false positives
+        * but given the aim is to provide input for a pull down list...
+        * 
+        * @param str      What to match
+        * @param config   Provides list of tokens to not lookup
+        * @return         Whether this item matches  
+        */
+       
+       public int compareTo(Object o) {
+               int result = getDisplayName().toLowerCase().compareTo(((IdPSite) o).getDisplayName().toLowerCase());
+               if (result == 0) {
+                       result = getDisplayName().compareTo(((IdPSite) o).getDisplayName());
+               }
+               return result;
+       }
+
+       static private boolean isMatch(EntityDescriptor entity, String str, WayfConfig config) {
+               
+               Enumeration input = new StringTokenizer(str);
+               while (input.hasMoreElements()) {
+                       String currentToken = (String) input.nextElement();
+
+                       if (config.isIgnoredForMatch(currentToken)) {                           
+                               continue;
+                       }
+                       
+                       currentToken = currentToken.toLowerCase(); 
+
+                       if (entity.getId().indexOf(currentToken) > -1) {
+                               return true; 
+                       }
+                                       
+                       Organization org = entity.getOrganization();
+                       
+                       if (org != null) {
+                               
+                               if (org.getName().toLowerCase().indexOf(currentToken) > -1) {
+                                       return true; 
+                               }
+                               
+                               if (org.getDisplayName().toLowerCase().indexOf(currentToken) > -1) {
+                                       return true; 
+                               }
+                                
+                       }
+               }
+               return false;
+       }
+       
+       static public Collection seachForMatchingOrigins(Metadata metadata,
+                                                                                                       String searchString, 
+                                                                                                       WayfConfig config)
+       {
+               TreeSet /*<IdPSite>*/ result = new TreeSet /*<IdPSite>*/ ();
+               Iterator /*<EntityDescriptor>*/ entities = Entities(metadata);
+               
+               while (entities.hasNext()) {
+                               
+                       EntityDescriptor entity = (EntityDescriptor) entities.next();
+                               
+                       if ((entity.isValid() &&
+                                entity.getIDPSSODescriptor(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS) != null) &&
+                                isMatch(entity, searchString, config)) {               
+
+                               result.add(new IdPSite(entity));
+                       }
+               } // check entities 
+               return result;
+       }
+       
+       static public Collection getIdPSites(Metadata metadata)
+       {
+               TreeSet /*<IdPSite>*/ result = new TreeSet /*<IdPSite>*/ ();
+               Iterator /*<EntityDescriptor>*/ entities = Entities(metadata);
+               
+               while (entities.hasNext()) {
+                       EntityDescriptor entity = (EntityDescriptor) entities.next();
+                       
+                       if (entity.isValid() &&
+                           entity.getIDPSSODescriptor(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS) != null) {
+
+                               result.add(new IdPSite(entity));
+                               }
+               } // iterate over all entities
+               return result;
+       }
+
+       /**
+        * entitiesIterator:
+        * 
+        * Given a metadata object return an iterator which will enumerate all the
+        * entities inside it.  There are two options for what is at the root of metadata
+        * (either a single entity or a single entities list) so we just create the right 
+        * sort of iterator
+        * 
+        * @param metadata:  What to traverse
+        * @return an iterator
+        */
+       
+       private static Iterator /*<EntityDescriptor>*/ Entities(Metadata metadata) {
+
+               EntitiesDescriptor entities = metadata.getRootEntities();
+               EntityDescriptor entity = metadata.getRootEntity();
+
+               if (entities != null) {
+                       return new EntityIterator(entities);
+               }
+               
+               return Collections.singleton(entity).iterator();
+       }
+       
+       private static class EntityIterator implements Iterator /*<EntityDescriptor>*/ {
+               
+               private Iterator /*<EntitiesDescriptor>*/ entitiesIterator;
+               private Iterator /*<EntityDescriptor>*/ entityIterator;
+               
+               /**
+               * An invariant of this class is that the inner iterator (entityIterator) should always be valid.
+               * This means that when the current one is at the end we step the outer iterator (entitiesIterator)
+               * along and get the next innter iterator.
+               * 
+               * However because the returned inner iterator may already be empty we need to 
+               * loop until we either get to the end of the outer iterator or the inner iterator has a value
+               * to return.  Think of it as priming a pump.
+               *
+               * This method does the work.  It is called at the start (in the constructor) and also whenever
+               * any innter iterator reaches the end.
+               */
+
+               private void getNextNonEmptyIterator() {
+                       while (!entityIterator.hasNext() && entitiesIterator.hasNext()) {
+                               entityIterator = new EntityIterator((EntitiesDescriptor) entitiesIterator.next());
+                       }
+               }
+               
+               private EntityIterator(EntitiesDescriptor entities)
+               {
+                       entitiesIterator = entities.getEntitiesDescriptors();
+                       entityIterator = entities.getEntityDescriptors();
+                       
+                       if (entitiesIterator == null) {
+                               entitiesIterator = new NullIterator /*<EntitiesDescriptor>*/();
+                       }
+                       
+                       if (entityIterator == null) {
+                               entityIterator = new NullIterator /*<EntityDescriptor>*/();
+                       }
+                       
+                       // prime the pump to get entityIterator valid.
+                       getNextNonEmptyIterator();
+               }
+               
+               
+               public boolean hasNext() {
+                       return entityIterator.hasNext();
+               }
+       
+               public Object /*EntityDescriptor*/ next() {
+                       Object /*EntityDescriptor*/ ret = entityIterator.next();
+
+                       //
+                       // make entityIterator valid
+                       ///
+                       getNextNonEmptyIterator();
+                       return ret;
+               }
+       
+               public void remove() {
+                       entityIterator.remove();
+               }
+               
+               // 
+               // Implementation note - should be removed in Java 5 and replaced by
+               // the iterator from an empty collection.
+               //
+               private static class NullIterator /*<E>*/ implements Iterator/*<E>*/ {
+
+                       public boolean hasNext() {
+                               return false;
+                       }
+
+                       public /*E*/ Object next() {
+                               throw new NoSuchElementException();
+                       }
+
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+               } //NullIterator        
+       } // Class EntitiesIterator
+}      
+
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/Origin.java b/src/edu/internet2/middleware/shibboleth/wayf/Origin.java
deleted file mode 100755 (executable)
index f934d5f..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package edu.internet2.middleware.shibboleth.wayf;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.StringTokenizer;
-
-/**
- * This class represents an Origin site in the shibboleth parlance.
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-
-public class Origin implements Comparable {
-
-       private String name = "";
-       private ArrayList aliases = new ArrayList();
-       private String handleService;
-
-       /**
-        * Gets the handleService for this origin.
-        * 
-        * @return Returns a String
-        */
-       public String getHandleService() {
-
-               return handleService;
-       }
-
-       /**
-        * Sets the handleService for this origin.
-        * 
-        * @param handleService
-        *            The handleService to set
-        */
-       public void setHandleService(String handleService) {
-
-               this.handleService = handleService;
-       }
-
-       /**
-        * Gets the origin name.
-        * 
-        * @return Returns a String
-        */
-       public String getName() {
-
-               return name;
-       }
-
-       public String getDisplayName() {
-
-               if (aliases.get(0) != null) {
-                       return (String) aliases.get(0);
-               } else {
-                       return getName();
-               }
-       }
-
-       public String getUrlEncodedName() throws UnsupportedEncodingException {
-
-               return URLEncoder.encode(name, "UTF-8");
-       }
-
-       /**
-        * Sets a name for this origin.
-        * 
-        * @param name
-        *            The name to set
-        */
-       public void setName(String name) {
-
-               this.name = name;
-       }
-
-       /**
-        * Gets all aliases for this origin.
-        * 
-        * @return Returns a String[]
-        */
-       public String[] getAliases() {
-
-               return (String[]) aliases.toArray(new String[0]);
-       }
-
-       /**
-        * Adds an alias for this origin.
-        * 
-        * @param alias
-        *            The aliases to set
-        */
-       public void addAlias(String alias) {
-
-               aliases.add(alias);
-       }
-
-       /**
-        * Determines if a given string matches one of the registered names/aliases of this origin.
-        * 
-        * @param str
-        *            The string to match on
-        */
-       public boolean isMatch(String str, WayfConfig config) {
-
-               Enumeration input = new StringTokenizer(str);
-               while (input.hasMoreElements()) {
-                       String currentToken = (String) input.nextElement();
-
-                       if (config.isIgnoredForMatch(currentToken)) {
-                               continue;
-                       }
-
-                       if (getName().toLowerCase().indexOf(currentToken.toLowerCase()) > -1) { return true; }
-                       Iterator aliasit = aliases.iterator();
-                       while (aliasit.hasNext()) {
-                               String alias = (String) aliasit.next();
-                               if (alias.toLowerCase().indexOf(currentToken.toLowerCase()) > -1) { return true; }
-                       }
-
-               }
-               return false;
-       }
-
-       /**
-        * @see java.lang.Comparable#compareTo(java.lang.Object)
-        */
-       public int compareTo(Object o) {
-
-               int result = getDisplayName().toLowerCase().compareTo(((Origin) o).getDisplayName().toLowerCase());
-               if (result == 0) {
-                       result = getDisplayName().compareTo(((Origin) o).getDisplayName());
-               }
-               return result;
-       }
-
-}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/OriginSet.java b/src/edu/internet2/middleware/shibboleth/wayf/OriginSet.java
deleted file mode 100755 (executable)
index 18883ff..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package edu.internet2.middleware.shibboleth.wayf;
-
-import java.util.Arrays;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import org.apache.log4j.Logger;
-
-/**
- * This class is used to create logical groupings of shibboleth Origin Sites. Each grouping is associated with a textual
- * name that might be displayed in a UI to accommodate user selection.
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-
-public class OriginSet {
-
-       private SortedSet origins = new TreeSet();
-       private static Logger log = Logger.getLogger(OriginSet.class.getName());
-       private String name = "";
-
-       public String getName() {
-
-               return name;
-       }
-
-       public void setName(String name) {
-
-               this.name = name;
-       }
-
-       public Origin[] getOrigins() {
-
-               Origin[] result = (Origin[]) origins.toArray(new Origin[0]);
-               Arrays.sort(result);
-               return result;
-       }
-
-       public void addOrigin(Origin origin) {
-
-               if (origin.getHandleService() != null) {
-                       origins.add(origin);
-                       log.debug("Adding origin site :" + origin.getName() + ":  to set.");
-               }
-       }
-
-}
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/OriginSitesDigester.java b/src/edu/internet2/middleware/shibboleth/wayf/OriginSitesDigester.java
deleted file mode 100755 (executable)
index 2417d02..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package edu.internet2.middleware.shibboleth.wayf;
-
-import javax.xml.parsers.SAXParser;
-
-import org.xml.sax.XMLReader;
-
-import edu.internet2.middleware.shibboleth.common.ServletDigester;
-
-/**
- * @author Administrator
- * 
- * To change this generated comment edit the template variable "typecomment": Window>Preferences>Java>Templates. To
- * enable and disable the creation of type comments go to Window>Preferences>Java>Code Generation.
- */
-public class OriginSitesDigester extends ServletDigester {
-
-       protected String originClass = "edu.internet2.middleware.shibboleth.wayf.Origin";
-       protected String originSetClass = "edu.internet2.middleware.shibboleth.wayf.OriginSet";
-
-       private boolean configured = false;
-
-       /**
-        * Constructor for OriginSitesDigester.
-        */
-       public OriginSitesDigester() {
-
-               super();
-       }
-
-       /**
-        * Constructor for OriginSitesDigester.
-        * 
-        * @param parser
-        */
-       public OriginSitesDigester(SAXParser parser) {
-
-               super(parser);
-       }
-
-       /**
-        * Constructor for OriginSitesDigester.
-        * 
-        * @param reader
-        */
-       public OriginSitesDigester(XMLReader reader) {
-
-               super(reader);
-       }
-
-       /**
-        * @see Digester#configure()
-        */
-       protected void configure() {
-
-               if (configured == true) { return; }
-               push(new WayfOrigins());
-               // Digest sites that are nested in a group
-               addObjectCreate("SiteGroup", originSetClass);
-               addSetNext("SiteGroup", "addOriginSet", originSetClass);
-               addCallMethod("SiteGroup", "setName", 1);
-               addCallParam("SiteGroup", 0, "Name");
-
-               addObjectCreate("SiteGroup/OriginSite", originClass);
-               addSetNext("SiteGroup/OriginSite", "addOrigin", originClass);
-               addCallMethod("SiteGroup/OriginSite", "setName", 1);
-               addCallParam("SiteGroup/OriginSite", 0, "Name");
-               addSetProperties("SiteGroup/OriginSite");
-               addCallMethod("SiteGroup/OriginSite/Alias", "addAlias", 0);
-               addCallMethod("SiteGroup/OriginSite", "setHandleService", 1);
-               addCallParam("SiteGroup/OriginSite/HandleService", 0, "Location");
-
-               // Digest sites without nesting and add them to the default group
-               addObjectCreate("OriginSite", originSetClass);
-               addSetNext("OriginSite", "addOriginSet", originSetClass);
-               addObjectCreate("OriginSite", originClass);
-               addSetNext("OriginSite", "addOrigin", originClass);
-               addCallMethod("OriginSite", "setName", 1);
-               addCallParam("OriginSite", 0, "Name");
-               addSetProperties("OriginSite");
-               addCallMethod("OriginSite/Alias", "addAlias", 0);
-               addCallMethod("OriginSite", "setHandleService", 1);
-               addCallParam("OriginSite/HandleService", 0, "Location");
-
-               // Handle 1.3 Metadata
-        addObjectCreate("EntitiesDescriptor", originSetClass);
-               addSetNext("EntitiesDescriptor", "addOriginSet", originSetClass);
-               addCallMethod("EntitiesDescriptor", "setName", 1);
-               addCallParam("EntitiesDescriptor", 0, "Name");
-
-               addObjectCreate("EntitiesDescriptor/EntityDescriptor", originClass);
-               addSetNext("EntitiesDescriptor/EntityDescriptor", "addOrigin", originClass);
-
-               addCallMethod("EntitiesDescriptor/EntityDescriptor", "setName", 1);
-               addCallParam("EntitiesDescriptor/EntityDescriptor", 0, "entityID");
-
-               addCallMethod("EntitiesDescriptor/EntityDescriptor/Organization/OrganizationName", "addAlias", 0);
-               addCallMethod("EntitiesDescriptor/EntityDescriptor/Organization/OrganizationDisplayName", "addAlias", 0);
-                
-               addCallMethod("EntitiesDescriptor/EntityDescriptor/IDPSSODescriptor/SingleSignOnService", "setHandleService", 1);
-               addCallParam("EntitiesDescriptor/EntityDescriptor/IDPSSODescriptor/SingleSignOnService", 0, "Location");
-                                
-               
-               
-               configured = true;
-
-       }
-
-}
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/WayfOrigins.java b/src/edu/internet2/middleware/shibboleth/wayf/WayfOrigins.java
deleted file mode 100755 (executable)
index 967bf97..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package edu.internet2.middleware.shibboleth.wayf;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-
-import org.apache.log4j.Logger;
-
-/**
- * This class is a container for OriginSets, allowing lookup and searching of the same.
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-
-public class WayfOrigins {
-
-       private HashMap origins = new HashMap();
-       private static Logger log = Logger.getLogger(WayfOrigins.class.getName());
-
-       public OriginSet[] getOriginSets() {
-
-               return (OriginSet[]) origins.values().toArray(new OriginSet[0]);
-       }
-
-       public void addOriginSet(OriginSet originSet) {
-
-               if (origins.containsKey(originSet.getName())) {
-                       OriginSet previousOrigins = (OriginSet) origins.get(originSet.getName());
-                       Origin[] newOrigins = originSet.getOrigins();
-                       for (int i = 0; (i < newOrigins.length); i++) {
-                               previousOrigins.addOrigin(newOrigins[i]);
-                       }
-               } else {
-                       origins.put(originSet.getName(), originSet);
-               }
-               log.debug("Adding origin set :" + originSet.getName() + ": to configuration");
-       }
-
-       public String lookupHSbyName(String originName) {
-
-               if (originName != null) {
-                       Iterator originSetIt = origins.values().iterator();
-                       while (originSetIt.hasNext()) {
-
-                               OriginSet originSet = (OriginSet) originSetIt.next();
-                               Origin[] origins = originSet.getOrigins();
-                               for (int i = 0; (i < origins.length); i++) {
-                                       if (originName.equals(origins[i].getName())) { return origins[i].getHandleService(); }
-                               }
-                       }
-
-               }
-               return null;
-
-       }
-
-       public Origin[] seachForMatchingOrigins(String searchString, WayfConfig config) {
-
-               Iterator originSetIt = origins.values().iterator();
-               HashSet searchResults = new HashSet();
-               while (originSetIt.hasNext()) {
-
-                       OriginSet originSet = (OriginSet) originSetIt.next();
-                       Origin[] origins = originSet.getOrigins();
-                       for (int i = 0; (i < origins.length); i++) {
-                               if (origins[i].isMatch(searchString, config)) {
-                                       searchResults.add(origins[i]);
-                               }
-                       }
-               }
-               return (Origin[]) searchResults.toArray(new Origin[0]);
-       }
-
-}
index 9fd2046..a0300f1 100755 (executable)
@@ -19,6 +19,7 @@ package edu.internet2.middleware.shibboleth.wayf;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URLEncoder;
+import java.util.Collection;
 import java.util.Date;
 
 import javax.servlet.RequestDispatcher;
@@ -31,10 +32,11 @@ import javax.servlet.http.HttpServletResponse;
 import org.apache.log4j.Logger;
 import org.xml.sax.SAXException;
 
-import edu.internet2.middleware.shibboleth.common.ResourceWatchdog;
 import edu.internet2.middleware.shibboleth.common.ShibResource;
-import edu.internet2.middleware.shibboleth.common.ResourceWatchdogExecutionException;
 import edu.internet2.middleware.shibboleth.common.ShibResource.ResourceNotAvailableException;
+import edu.internet2.middleware.shibboleth.metadata.Metadata;
+import edu.internet2.middleware.shibboleth.metadata.provider.XMLMetadata;
+import edu.internet2.middleware.shibboleth.metadata.MetadataException;
 
 /**
  * A servlet implementation of the Shibboleth WAYF service. Allows a browser user to select from among a group of origin
@@ -48,11 +50,11 @@ public class WayfService extends HttpServlet {
        private String wayfConfigFileLocation;
        private String siteConfigFileLocation;
        private WayfConfig config;
-       private WayfOrigins originConfig;
-       private WayfCacheOptions wOptions = new WayfCacheOptions();
+       private Metadata metadata;
+       private WayfCacheOptions wSessionOptions = new WayfCacheOptions();
+       private WayfCacheOptions wPermOptions = new WayfCacheOptions();
        private static Logger log = Logger.getLogger(WayfService.class.getName());
-       ResourceWatchdog watchdog;
-
+       
        /**
         * @see GenericServlet#init()
         */
@@ -64,24 +66,28 @@ public class WayfService extends HttpServlet {
                log.info("Loading configuration from file.");
                configure();
 
-               log.info("Initailizing site metadata watchdog.");
+               log.info("Initializing site metadata & watchdog");
                try {
-                       watchdog = new SitesFileWatchdog(siteConfigFileLocation, this);
-                       watchdog.start();
+                       metadata = new XMLMetadata(siteConfigFileLocation);
                } catch (ResourceNotAvailableException e) {
                        log.error("Sites file watchdog could not be initialized: " + e);
+                       throw new ServletException(e);
+               } catch (MetadataException e) {
+                       log.error("Sites files could not be parsed" + e);
+                       throw new ServletException(e);
                }
 
                // Setup Cacheing options
-               wOptions.setDomain(config.getCacheDomain());
-               wOptions.setExpiration(config.getCacheExpiration());
+               wSessionOptions.setDomain(config.getCacheDomain());
+               wPermOptions.setDomain(config.getCacheDomain());
+               wPermOptions.setExpiration(config.getCacheExpiration());
 
                initViewConfig();
                log.info("WAYF initialization completed.");
        }
 
        /**
-        * Populates WayfConfig and WayfOrigins objects from file contents.
+        * Populates WayfConfig from file contents.
         */
        private void configure() throws UnavailableException {
 
@@ -98,26 +104,6 @@ public class WayfService extends HttpServlet {
                        log.fatal("Error reading WAYF configuration file.", ioe);
                        throw new UnavailableException("Error reading WAYF configuration file.");
                }
-
-               loadSiteConfig();
-       }
-
-       private void loadSiteConfig() throws UnavailableException {
-
-               try {
-
-                       InputStream siteIs = new ShibResource(siteConfigFileLocation, this.getClass()).getInputStream();
-                       OriginSitesDigester siteDigester = new OriginSitesDigester();
-                       siteDigester.setValidating(true);
-                       originConfig = (WayfOrigins) siteDigester.parse(siteIs);
-
-               } catch (SAXException se) {
-                       log.fatal("Error parsing site file.", se);
-                       throw new UnavailableException("Error parsing site file.");
-               } catch (IOException ioe) {
-                       log.fatal("Error reading site file.", ioe);
-                       throw new UnavailableException("Error reading site file.");
-               }
        }
 
        /**
@@ -125,7 +111,6 @@ public class WayfService extends HttpServlet {
         */
        private void initViewConfig() {
 
-               getServletContext().setAttribute("originsets", getOrigins().getOriginSets());
                getServletContext().setAttribute("supportContact", config.getSupportContact());
                getServletContext().setAttribute("helpText", config.getHelpText());
                getServletContext().setAttribute("searchResultEmptyText", config.getSearchResultEmptyText());
@@ -145,7 +130,7 @@ public class WayfService extends HttpServlet {
                siteConfigFileLocation = getServletConfig().getInitParameter("SiteConfigFileLocation");
                if (siteConfigFileLocation == null) {
                        log.warn("No SiteonfigFileLocation parameter found... using default location.");
-                       siteConfigFileLocation = "/sites.xml";
+                       siteConfigFileLocation = "/conf/metadata.xml";
                }
 
        }
@@ -169,7 +154,7 @@ public class WayfService extends HttpServlet {
                try {
                        if (requestType.equals("deleteFromCache")) {
                                log.debug("Deleting saved HS from cache");
-                               WayfCacheFactory.getInstance(config.getCacheType(), wOptions).deleteHsFromCache(req, res);
+                               WayfCacheFactory.getInstance(config.getCacheType(), wPermOptions).deleteHsFromCache(req, res);
                                handleLookup(req, res);
                        } else if (WayfCacheFactory.getInstance(config.getCacheType()).hasCachedHS(req)) {
                                forwardToHS(req, res, WayfCacheFactory.getInstance(config.getCacheType()).getCachedHS(req));
@@ -185,13 +170,6 @@ public class WayfService extends HttpServlet {
                }
        }
 
-       public void destroy() {
-
-               if (watchdog != null && watchdog.isAlive()) {
-                       watchdog.interrupt();
-               }
-       }
-
        /**
         * Displays a WAYF selection page.
         */
@@ -199,13 +177,17 @@ public class WayfService extends HttpServlet {
 
                try {
                        if ((getSHIRE(req) == null) || (getTarget(req) == null)) { throw new WayfException(
-                                       "Invalid or missing data from SHIRE"); }
+                                       "Invalid or missing data from SHIRE"); 
+                       }
+
+                       req.setAttribute("sites", IdPSite.getIdPSites(metadata));
                        req.setAttribute("shire", getSHIRE(req));
                        req.setAttribute("target", getTarget(req));
                        String providerId = getProviderId(req);
                        if (providerId != null) {
                                req.setAttribute("providerId", providerId);
                        }
+                       
                        req.setAttribute("time", new Long(new Date().getTime() / 1000).toString()); // Unix Time
                        req.setAttribute("requestURL", req.getRequestURI().toString());
 
@@ -225,10 +207,11 @@ public class WayfService extends HttpServlet {
         */
        private void handleSearch(HttpServletRequest req, HttpServletResponse res) throws WayfException {
 
-               if (req.getParameter("string") != null) {
-                       Origin[] origins = getOrigins().seachForMatchingOrigins(req.getParameter("string"), config);
-                       if (origins.length != 0) {
-                               req.setAttribute("searchresults", origins);
+               String parameter = req.getParameter("string"); 
+               if (parameter != null) {
+                       Collection sites = IdPSite.seachForMatchingOrigins(metadata, parameter, config);
+                       if (sites.size() != 0) {
+                               req.setAttribute("searchresults", sites);
                        } else {
                                req.setAttribute("searchResultsEmpty", "true");
                        }
@@ -242,12 +225,28 @@ public class WayfService extends HttpServlet {
        private void handleSelection(HttpServletRequest req, HttpServletResponse res) throws WayfException {
 
                log.debug("Processing handle selection: " + req.getParameter("origin"));
-               String handleService = getOrigins().lookupHSbyName(req.getParameter("origin"));
+               String handleService = null;
+               try {
+                       //
+                       // If we have had a refresh between then and now the following will fail
+                       //
+                       handleService = metadata.lookup(req.getParameter("origin")).getIDPSSODescriptor(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS).getSingleSignOnServiceManager().getDefaultEndpoint().getLocation(); 
+               } 
+               catch (Exception ex) {
+                       log.error("Error dispatching to IdP", ex);
+               }
+               
+               
                if (handleService == null) {
                        handleLookup(req, res);
                } else {
-                       if ((req.getParameter("cache") != null) && req.getParameter("cache").equalsIgnoreCase("TRUE")) {
-                               WayfCacheFactory.getInstance(config.getCacheType(), wOptions).addHsToCache(handleService, req, res);
+                       if ((req.getParameter("cache") != null)) {
+                               if (req.getParameter("cache").equalsIgnoreCase("session")) {
+                                       WayfCacheFactory.getInstance(config.getCacheType(), wSessionOptions).addHsToCache(handleService, req, res);
+                               }
+                               else if (req.getParameter("cache").equalsIgnoreCase("perm")) {
+                                       WayfCacheFactory.getInstance(config.getCacheType(), wPermOptions).addHsToCache(handleService, req, res);
+                               }
                        }
                        forwardToHS(req, res, handleService);
                }
@@ -347,60 +346,5 @@ public class WayfService extends HttpServlet {
                        if (attr == null || attr.length() == 0) { return null; }
                        return attr;
                }
-       }
-
-       private WayfOrigins getOrigins() {
-
-               synchronized (originConfig) {
-                       return originConfig;
-               }
-       }
-
-       private void reloadOriginMetadata() throws UnavailableException {
-
-               WayfOrigins safetyCache = getOrigins();
-               try {
-                       synchronized (originConfig) {
-                               loadSiteConfig();
-                               getServletContext().setAttribute("originsets", getOrigins().getOriginSets());
-                       }
-
-               } catch (UnavailableException e) {
-                       log.error("Failed to load updated origin site metadata: " + e);
-                       synchronized (originConfig) {
-                               originConfig = safetyCache;
-                       }
-                       throw e;
-               }
-       }
-
-       private class SitesFileWatchdog extends ResourceWatchdog {
-
-               private WayfService wayfService;
-
-               private SitesFileWatchdog(String sitesFileLocation, WayfService wayfService)
-                               throws ResourceNotAvailableException {
-
-                       super(new ShibResource(sitesFileLocation, wayfService.getClass()));
-                       this.wayfService = wayfService;
-               }
-
-               /**
-                * @see edu.internet2.middleware.shibboleth.common.ResourceWatchdog#doOnChange()
-                */
-               protected void doOnChange() throws ResourceWatchdogExecutionException {
-
-                       try {
-                               wayfService.reloadOriginMetadata();
-                       } catch (UnavailableException e) {
-                               try {
-                                       log.error("Sites file at (" + resource.getURL().toString() + ") could not be loaded: " + e);
-                               } catch (IOException ioe) {
-                                       log.error("Sites file could not be loaded.");
-                               } finally {
-                                       throw new ResourceWatchdogExecutionException("Watchdog reload failed.");
-                               }
-                       }
-               }
-       }
+       }       
 }
index 8f8f6e9..2c2f0d6 100755 (executable)
        <jsp:useBean id="time" scope="request" class="java.lang.String"/>
        <jsp:useBean id="searchResultEmptyText" scope="application" class="java.lang.String"/>
        <jsp:useBean id="logoLocation" scope="application" class="java.lang.String"/>
-       <logic:present name="searchresults" scope="request">
-               <jsp:useBean id="searchresults" scope="request" type="edu.internet2.middleware.shibboleth.wayf.Origin[]"/>
-       </logic:present>
 <head>
-               <link rel="stylesheet" title="normal" type="text/css" href="wayf.css" /><title>InQueue: Identity Provider Selection</title></head>
-       <body>
+       <link rel="stylesheet" title="normal" type="text/css" href="wayf.css" />
+       <title>InQueue: Identity Provider Selection</title>
+</head>
 
-               <div class="head">
-                       <h1>Select an identity provider</h1>
-               </div>
+<body>
+    <div class="head">
+       <h1>Select an identity provider</h1>
+    </div>
 
-               <div class="selector">
-                       <p class="text"><bean:write name="helpText" /></p>
+    <div class="selector">
+       <p class="text"><bean:write name="helpText" /></p>
+       <div class="list">
 
-                       <div class="list">
+           <h2>Choose from a list:</h2>
 
-                               <h2>Choose from a list:</h2>
-                               <logic:iterate id="originset" name="originsets">
-                               <form method="get" action="<bean:write name="requestURL" />">
-                                       <p>
-                                       <input type="hidden" name="shire" value="<bean:write name="shire" />" />
-                                       <input type="hidden" name="target" value="<bean:write name="target" />" />
-                                       <logic:present name="providerId" scope="request">
-                                               <input type="hidden" name="providerId" value="<bean:write name="providerId" />" />
-                                       </logic:present>
-                                       <logic:present name="time" scope="request">
-                                               <input type="hidden" name="time" value="<bean:write name="time" />" />
-                                       </logic:present>
-                                       <input type="hidden" name="action" value="selection" />
-                                       <select name="origin">  
-                                               <logic:iterate id="origin" name="originset" property="origins">
-                                                       <option value="<jsp:getProperty name="origin" property="name" />">
-                                                               <jsp:getProperty name="origin" property="displayName" />
-                                                       </option>
-                                               </logic:iterate>
-                                       </select>
-                                               <input type="submit" value="Select" />
-                                               <input type="checkbox" checked="checked" name="cache" value="TRUE" /><span class="warning">Remember my selection on this computer.</span>
-                                               </p>
-                                       </form>
-                                       </logic:iterate>
+           <form method="get" action="<bean:write name="requestURL" />">
+               <p>
+                   <input type="hidden" name="shire" value="<bean:write name="shire" />" />
+                   <input type="hidden" name="target" value="<bean:write name="target" />" />
+                   <logic:present name="providerId" scope="request">
+                           <input type="hidden" name="providerId" value="<bean:write name="providerId" />" />
+                   </logic:present>
+                   <logic:present name="time" scope="request">
+                               <input type="hidden" name="time" value="<bean:write name="time" />" />
+                   </logic:present>
+                   <input type="hidden" name="action" value="selection" />
+                   <select name="origin">      
+                       <logic:iterate id="site" name="sites">
+                           <option value="<jsp:getProperty name="site" property="name" />">
+                                       <jsp:getProperty name="site" property="displayName" />
+                           </option>
+                       </logic:iterate>
+                   </select>
+                   <input type="submit" value="Select" />
+                   <select name="cache">
+                       <option value="false"> Do not remember
+                       <option value="session" selected> Remember for session
+                       <option value="perm"> Remember for a week
+                   </select>
+               </p>
+           </form>
 
-                               </div>
-                               <div class="search">
-                               <span class="option">or</span>
-                               <h2>Search by keyword:</h2>
+           <div class="search">
+               <span class="option">or</span>
 
-                                       <form method="get" action="<bean:write name="requestURL" />">
-                                               <p>
-                                                       <input type="hidden" name="shire" value="<bean:write name="shire" />" />
-                                                       <input type="hidden" name="target" value="<bean:write name="target" />" />
-                                                       <logic:present name="providerId" scope="request">
-                                                               <input type="hidden" name="providerId" value="<bean:write name="providerId" />" />
-                                                       </logic:present>
-                                                       <logic:present name="time" scope="request">
-                                                               <input type="hidden" name="time" value="<bean:write name="time" />" />
-                                                       </logic:present>
-                                                       <input type="hidden" name="action" value="search" />
-                                                       <input type="text" name="string" />
-                                                       <input type="submit" value="Search" />
-                                               </p>
-                                       </form>
-                                       <logic:present name="searchResultsEmpty" scope="request">
-                                               <p class="error"><bean:write name="searchResultEmptyText" /></p>
-                                       </logic:present>
-                                       <logic:present name="searchresults" scope="request">
-                                               <h3>Search results:</h3>
-                                               <form method="get" action="<bean:write name="requestURL" />">
-                                                       <ul>
-                                                       <logic:iterate id="currResult" name="searchresults">
-                                                               <li>
-                                                               <input type="radio" name="origin" value="<jsp:getProperty name="currResult" property="name" />" /><jsp:getProperty name="currResult" property="displayName" />
-                                                               </li>
-                                                       </logic:iterate>
-                                                       </ul>
-                                                       <p>
-                                                               <input type="hidden" name="shire" value="<bean:write name="shire" />" />
-                                                               <input type="hidden" name="target" value="<bean:write name="target" />" />
-                                                               <logic:present name="providerId" scope="request">
-                                                                       <input type="hidden" name="providerId" value="<bean:write name="providerId" />" />
-                                                               </logic:present>
-                                                               <logic:present name="time" scope="request">
-                                                                       <input type="hidden" name="time" value="<bean:write name="time" />" />
-                                                               </logic:present>
-                                                               <input type="hidden" name="action" value="selection" />
-                                                               <input type="submit" value="Select" />
-                                                               <input type="checkbox" checked="checked" name="cache" value="TRUE" /><span class="warning">Remember my selection on this computer.</span>
-                                                       </p>
-                                               </form> 
-                                       </logic:present>
+               <h2>Search by keyword:</h2>
 
-                               </div>
-                       </div>
-                       <div class="footer">
+               <form method="get" action="<bean:write name="requestURL" />">
+                   <p>
+                       <input type="hidden" name="shire" value="<bean:write name="shire" />" />
+                       <input type="hidden" name="target" value="<bean:write name="target" />" />
+                       <logic:present name="providerId" scope="request">
+                           <input type="hidden" name="providerId" value="<bean:write name="providerId" />" />
+                       </logic:present>
+                       <logic:present name="time" scope="request">
+                           <input type="hidden" name="time" value="<bean:write name="time" />" />
+                       </logic:present>
+                       <input type="hidden" name="action" value="search" />
+                       <input type="text" name="string" />
+                       <input type="submit" value="Search" />
+                   </p>
+               </form>
 
-                               <p class="text">Need assistance? Send mail to <a href="mailto:inqueue-support@internet2.edu">inqueue-support@internet2.edu</a> with description.</p>
-                               <div class="logo"><img src="./images/internet2.gif" alt="InQueue" /></div>
-                       </div>
+               <logic:present name="searchResultsEmpty" scope="request">
+                   <p class="error"><bean:write name="searchResultEmptyText" /></p>
+               </logic:present>
+
+               <logic:present name="searchresults" scope="request">
+                   <h3>Search results:</h3>
+                   <form method="get" action="<bean:write name="requestURL" />">
+                       <ul>
+                           <logic:iterate id="currResult" name="searchresults">
+                               <li>
+                                   <input type="radio" name="origin" value="<jsp:getProperty name="currResult" property="name" />" />
+                                   <jsp:getProperty name="currResult" property="displayName" />
+                               </li>
+                           </logic:iterate>
+                       </ul>
+                       <p>
+                           <input type="hidden" name="shire" value="<bean:write name="shire" />" />
+                           <input type="hidden" name="target" value="<bean:write name="target" />" />
+                           <logic:present name="providerId" scope="request">
+                                       <input type="hidden" name="providerId" value="<bean:write name="providerId" />" />
+                           </logic:present>
+                           <logic:present name="time" scope="request">
+                                       <input type="hidden" name="time" value="<bean:write name="time" />" />
+                           </logic:present>
+                           <input type="hidden" name="action" value="selection" />
+                           <input type="submit" value="Select" />
+                           <select name="cache">
+                               <option value="false"> Do not remember
+                               <option value="session" selected> Remember for session
+                               <option value="perm"> Remember for a week
+                           </select>
+                       </p>
+                   </form>     
+               </logic:present>
+
+           </div>
+       </div>
+
+       <div class="footer">
+           <p class="text">Need assistance? Send mail to <a href="mailto:inqueue-support@internet2.edu">inqueue-support@internet2.edu</a> with description.</p>
+           <div class="logo"><img src="./images/internet2.gif" alt="InQueue" /></div>
+       </div>
                        
-       </body></html>
+</body>
+</html>