Major WAYF code clean up removing needed for Digester and BeanUtils - application...
authorlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 28 Sep 2005 13:06:09 +0000 (13:06 +0000)
committerlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 28 Sep 2005 13:06:09 +0000 (13:06 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1867 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

15 files changed:
src/conf/wayfconfig.xml
src/edu/internet2/middleware/shibboleth/common/ServletDigester.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/CookieWayfCache.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/NullWayfCache.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/SamlIdPCookie.java [new file with mode: 0644]
src/edu/internet2/middleware/shibboleth/wayf/SessionWayfCache.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/WayfCache.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/WayfCacheBase.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/WayfCacheFactory.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/WayfCacheOptions.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/WayfConfig.java
src/edu/internet2/middleware/shibboleth/wayf/WayfConfigDigester.java [deleted file]
src/edu/internet2/middleware/shibboleth/wayf/WayfService.java
src/edu/internet2/middleware/shibboleth/xml/Parser.java
src/schemas/wayfconfig.xsd

index f5872ec..50ebecf 100644 (file)
@@ -1,6 +1,7 @@
 <?xml version="1.0"?>
-<WayfConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../schemas/wayfconfig.xsd" 
-       cacheType="COOKIES" 
+<WayfConfig 
+       xmlns="urn:mace:shibboleth:wayf:config:1.0" 
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        cacheExpiration="604800"        
        supportContact="mailto:root@localhost" 
        logoLocation="images/logo.jpg">
diff --git a/src/edu/internet2/middleware/shibboleth/common/ServletDigester.java b/src/edu/internet2/middleware/shibboleth/common/ServletDigester.java
deleted file mode 100755 (executable)
index 9733dba..0000000
+++ /dev/null
@@ -1,169 +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.common;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Enumeration;
-import java.util.Properties;
-import java.util.StringTokenizer;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.apache.commons.digester.Digester;
-import org.apache.log4j.Logger;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-import org.xml.sax.XMLReader;
-
-/**
- * This class is a jakarta Digester style parser that will pull schemas from /WEB-INF/schemas, if they exist.
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-
-public class ServletDigester extends Digester {
-
-       private static Logger log = Logger.getLogger(ServletDigester.class.getName());
-
-       public ServletDigester() {
-
-               super();
-               setErrorHandler(new PassThruErrorHandler());
-       }
-
-       public ServletDigester(SAXParser parser) {
-
-               super(parser);
-               super.setErrorHandler(new PassThruErrorHandler());
-       }
-
-       public ServletDigester(XMLReader reader) {
-
-               super(reader);
-               super.setErrorHandler(new PassThruErrorHandler());
-       }
-
-       /**
-        * @see org.xml.sax.EntityResolver#resolveEntity(String, String)
-        */
-       public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
-
-               log.debug("Resolving entity for System ID: " + systemId);
-               if (systemId != null) {
-                       StringTokenizer tokenString = new StringTokenizer(systemId, "/");
-                       String xsdFile = "";
-                       while (tokenString.hasMoreTokens()) {
-                               xsdFile = tokenString.nextToken();
-                       }
-                       if (xsdFile.endsWith(".xsd")) {
-                               InputStream stream;
-                               try {
-                                       stream = new ShibResource("/schemas/" + xsdFile, this.getClass()).getInputStream();
-                               } catch (IOException ioe) {
-                                       log.error("Error loading schema: " + xsdFile + ": " + ioe);
-                                       return null;
-                               }
-                               if (stream != null) { return new InputSource(stream); }
-                       }
-               }
-               return null;
-
-       }
-
-       /**
-        * Return the SAXParser we will use to parse the input stream. If there is a problem creating the parser, return
-        * <code>null</code>.
-        */
-       public SAXParser getParser() {
-
-               // Return the parser we already created (if any)
-               if (parser != null) { return (parser); }
-
-               // Create and return a new parser
-               synchronized (this) {
-                       try {
-                               if (factory == null) {
-                                       factory = SAXParserFactory.newInstance();
-                               }
-                               factory.setNamespaceAware(namespaceAware);
-                               factory.setValidating(validating);
-                               if (validating) {
-                                       factory.setFeature("http://xml.org/sax/features/namespaces", true);
-                                       factory.setFeature("http://xml.org/sax/features/validation", true);
-                                       factory.setFeature("http://apache.org/xml/features/validation/schema", true);
-                                       factory.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);
-                               }
-                               parser = factory.newSAXParser();
-                               if (validating) {
-
-                                       Properties schemaProps = new Properties();
-                                       schemaProps.load(new ShibResource("/conf/schemas.properties", this.getClass()).getInputStream());
-                                       String schemaLocations = "";
-                                       Enumeration schemas = schemaProps.propertyNames();
-                                       while (schemas.hasMoreElements()) {
-                                               String ns = (String) schemas.nextElement();
-                                               schemaLocations += ns + " " + schemaProps.getProperty(ns) + " ";
-                                       }
-                                       log.debug("Overriding schema locations for the following namespace: " + schemaLocations);
-                                       parser.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation",
-                                                       schemaLocations);
-                               }
-                               return (parser);
-                       } catch (Exception e) {
-                               log.error("Error during Digester initialization", e);
-                               return (null);
-                       }
-               }
-
-       }
-
-       /**
-        * Sax <code>ErrorHandler</code> that passes all errors up as new exceptions.
-        */
-
-       public class PassThruErrorHandler implements ErrorHandler {
-
-               /**
-                * @see org.xml.sax.ErrorHandler#error(SAXParseException)
-                */
-               public void error(SAXParseException arg0) throws SAXException {
-
-                       throw new SAXException("Error parsing xml file: " + arg0);
-               }
-
-               /**
-                * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException)
-                */
-               public void fatalError(SAXParseException arg0) throws SAXException {
-
-                       throw new SAXException("Error parsing xml file: " + arg0);
-               }
-
-               /**
-                * @see org.xml.sax.ErrorHandler#warning(SAXParseException)
-                */
-               public void warning(SAXParseException arg0) throws SAXException {
-
-                       throw new SAXException("Error parsing xml file: " + arg0);
-               }
-
-       }
-}
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/CookieWayfCache.java b/src/edu/internet2/middleware/shibboleth/wayf/CookieWayfCache.java
deleted file mode 100755 (executable)
index 231329b..0000000
+++ /dev/null
@@ -1,103 +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.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Implementation of <code>WayfCache</code> that uses Http Cookies to cache user selections.
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-public class CookieWayfCache extends WayfCacheBase implements WayfCache {
-
-       private int expiration;
-       private String domain;
-
-       /**
-        * Constructs a <code>CookieWayfCache</code>
-        * 
-        * @param expiration
-        *            Cache validity period in seconds
-        * @param domain
-        *            Domain to which the cookie will be released
-        */
-       public CookieWayfCache(int expiration, String domain) {
-
-               this.expiration = expiration;
-               if (domain != null && domain != "") {
-                       this.domain = domain;
-               }
-       }
-
-       /**
-        * @see WayfCache#addHsToCache(HttpServletRequest)
-        */
-       public void addHsToCache(String handleService, HttpServletRequest req, HttpServletResponse res) {
-
-               Cookie cacheCookie = new Cookie("edu.internet2.middleware.shibboleth.wayf.selectedHandleService", handleService);
-               configureCookie(cacheCookie);
-               res.addCookie(cacheCookie);
-       }
-
-       /**
-        * @see WayfCache#deleteHsFromCache(HttpServletRequest)
-        */
-       public void deleteHsFromCache(HttpServletRequest req, HttpServletResponse res) {
-
-               Cookie[] cookies = req.getCookies();
-               if (cookies == null) { return; }
-               for (int i = 0; i < cookies.length; i++) {
-                       if (cookies[i].getName().equals("edu.internet2.middleware.shibboleth.wayf.selectedHandleService")) {
-                               configureCookie(cookies[i]);
-                               cookies[i].setMaxAge(0);
-                               res.addCookie(cookies[i]);
-                       }
-               }
-       }
-
-       /**
-        * @see WayfCache#getCachedHS(HttpServletRequest)
-        */
-       public String getCachedHS(HttpServletRequest req) {
-
-               Cookie[] cookies = req.getCookies();
-               if (cookies != null) {
-                       for (int i = 0; i < cookies.length; i++) {
-                               if (cookies[i].getName().equals("edu.internet2.middleware.shibboleth.wayf.selectedHandleService")) { return cookies[i]
-                                               .getValue(); }
-                       }
-               }
-               return null;
-       }
-
-       private void configureCookie(Cookie cookie) {
-
-               cookie.setComment("Used to cache selection of a user's Shibboleth Handle Service");
-               cookie.setPath("/");
-
-               if (expiration > 0) {
-                       cookie.setMaxAge(expiration);
-               }
-               if (domain != null && domain != "") {
-                       cookie.setDomain(domain);
-               }
-       }
-
-}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/NullWayfCache.java b/src/edu/internet2/middleware/shibboleth/wayf/NullWayfCache.java
deleted file mode 100755 (executable)
index b956b06..0000000
+++ /dev/null
@@ -1,62 +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.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Implementaton of the <code>WayfCache</code> interface that does no cacheing of user selections.
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-
-public class NullWayfCache implements WayfCache {
-
-       /**
-        * @see WayfCache#addHsToCache(HttpServletRequest)
-        */
-       public void addHsToCache(String handleService, HttpServletRequest req, HttpServletResponse res) {
-
-       // don't do anything
-       }
-
-       /**
-        * @see WayfCache#deleteHsFromCache(HttpServletRequest)
-        */
-       public void deleteHsFromCache(HttpServletRequest req, HttpServletResponse res) {
-
-       // don't do anything
-       }
-
-       /**
-        * @see WayfCache#getCachedHS(HttpServletRequest)
-        */
-       public String getCachedHS(HttpServletRequest req) {
-
-               return null;
-       }
-
-       /**
-        * @see WayfCache#hasCachedHS(HttpServletRequest)
-        */
-       public boolean hasCachedHS(HttpServletRequest req) {
-
-               return false;
-       }
-
-}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/SamlIdPCookie.java b/src/edu/internet2/middleware/shibboleth/wayf/SamlIdPCookie.java
new file mode 100644 (file)
index 0000000..36a180f
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * 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.ArrayList;
+import java.util.Iterator;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.bouncycastle.util.encoders.Base64;
+
+/**
+ * Implementation of the <code>_saml_idp </code> cookie.
+ * 
+ * Note that any SamlIdPCookie is only valid for as long as the reqest/response 
+ * parameters provided to getIdPCookie remain valid.
+ * 
+ * @author Rod Widdowson
+ *
+ */
+public class SamlIdPCookie  {
+
+       private static final String COOKIE_NAME = "_saml_idp";
+
+       private final HttpServletRequest req;
+       private final HttpServletResponse res;
+       private final String domain;
+       private final ArrayList /*<String>*/ idPList = new ArrayList/*<String>*/();
+       
+       /**
+        * Constructs a <code>SamlIdPCookie</code> from the provided string (which is the raw data 
+        * 
+        * @param codedData
+        *            the information read from the cookie
+        * @param domain - if non null the domain for any *created* cookie.
+        */
+       private SamlIdPCookie(String codedData, HttpServletRequest req, HttpServletResponse res, String domain) {
+               
+               this.req = req;
+               this.res = res;
+               this.domain = domain;
+               
+               int start;
+               int end;
+               
+               if (codedData == null || codedData.equals("")) {
+                       return;
+               }
+               //
+               // Because there are spaces in the data the cookie may be returned enclosed in quotes
+               //
+               if (codedData.charAt(0) == '"' && codedData.charAt(codedData.length()-1) == '"') {
+                       codedData= codedData.substring(1,codedData.length()-1);
+               }
+               
+               
+               start = 0;
+               end = codedData.indexOf(' ', start);
+               while (end > 0) {
+                       String value = codedData.substring(start, end);
+                       start = end + 1;
+                       end = codedData.indexOf(' ', start);
+                       if (!value.equals("")) {
+                           idPList.add(new String(Base64.decode(value)));
+                       }
+               }
+               if (start < codedData.length()) {
+                       String value = codedData.substring(start);
+                       if (!value.equals("")) {
+                           idPList.add(new String(Base64.decode(value)));
+                       }
+               }
+       }
+       /**
+        * Create a SamlCookie with no data inside.
+        * @param domain - if non null, the domain of the new cookie 
+        *
+        */
+       public SamlIdPCookie(HttpServletRequest req, HttpServletResponse res, String domain) {
+               this.req = req;
+               this.res = res;
+               this.domain = domain;
+       }
+
+       /**
+        * Add the specified Shibboleth IdP Name to the cookie list or move to 
+        * the front and then write it back.
+        * 
+        * We always add to the front (and remove from wherever it was)
+        * 
+        * @param idPName    - The name to be added
+        * @param expiration - The expiration of the cookie or zero if it is to be unchanged
+        */
+       public void addIdPName(String idPName, int expiration) {
+
+               idPList.remove(idPName);
+               idPList.add(0, idPName);
+
+               writeCookie(expiration);
+       }
+
+       /**
+        * Return an iterator over the list of IdPNames 
+        * @param which
+        * @return
+        */
+
+       public Iterator/*<String>*/ iterator() {
+
+               return idPList.iterator();
+       }
+       
+       /**
+        * Delete the <b>entire<\b> cookie contents
+        */
+
+       public static void deleteCookie(HttpServletRequest req, HttpServletResponse res) {
+               Cookie cookie = getCookie(req);
+               
+               if (cookie == null) { 
+                       return; 
+               }
+               cookie.setMaxAge(0);
+               res.addCookie(cookie);
+       }
+
+       /**
+        * Load up the cookie and convert it into a SamlIdPCookie.  If there is no
+        * underlying cookie return a null one.
+        * @param domain - if this is set then any <b>created</b> cookies are set to this domain 
+        */
+       
+       public static SamlIdPCookie getIdPCookie(HttpServletRequest req, HttpServletResponse res, String domain) {
+               Cookie cookie = getCookie(req);
+               
+               if (cookie == null) {
+                       return new SamlIdPCookie(req, res, domain);
+               } else {
+                       return new SamlIdPCookie(cookie.getValue(), req, res, domain);
+               }
+       }
+
+       /**
+        * Remove origin from the cachedata and write it back.
+        * @param origin
+        */
+       
+       public void deleteIdPName(String origin) {
+               idPList.remove(origin);
+               writeCookie(0);
+       }
+
+       private void writeCookie(int expiration)
+       {
+               Cookie cookie = getCookie(req);
+               
+               if (idPList.size() == 0) {
+                       //
+                       // Nothing to write, so delete the cookie
+                       //
+                       cookie.setMaxAge(0);
+                       res.addCookie(cookie);
+                       return;
+               }
+
+               //
+               // Otherwise encode up the cookie
+               //
+               
+               StringBuffer buffer = new StringBuffer();
+               Iterator /*<String>*/ it = idPList.iterator();
+               
+               while (it.hasNext()) {
+                       String next = (String) it.next();
+                       String what = new String(Base64.encode(next.getBytes()));
+                       buffer.append(what).append(' ');
+               }
+               
+               String value = buffer.toString();
+               
+               if (cookie == null) { 
+                       cookie = new Cookie(COOKIE_NAME, value);
+               } else {
+                       cookie.setValue(value);
+               }
+               cookie.setComment("Used to cache selection of a user's Shibboleth IdP");
+               cookie.setPath("/");
+
+               if (expiration > 0) {
+                       cookie.setMaxAge(expiration);
+               }
+               if (domain != null && domain != "") {
+                       cookie.setDomain(domain);
+               }
+               res.addCookie(cookie);
+       
+       }
+
+       private static Cookie getCookie(HttpServletRequest req) {
+               
+               Cookie[] cookies = req.getCookies();
+               if (cookies != null) {
+                       for (int i = 0; i < cookies.length; i++) {
+                               if (cookies[i].getName().equals(COOKIE_NAME)) { 
+                                       return cookies[i];
+                               }
+                       }
+               }
+               return null;
+       }
+}
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/SessionWayfCache.java b/src/edu/internet2/middleware/shibboleth/wayf/SessionWayfCache.java
deleted file mode 100755 (executable)
index e895fa1..0000000
+++ /dev/null
@@ -1,76 +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.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-/**
- * Implementation of <code>WayfCache</code> that uses Java Servlet Sessions to cache user selections.
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-
-public class SessionWayfCache extends WayfCacheBase implements WayfCache {
-
-       private int expiration;
-
-       /**
-        * @param expiration
-        *            The time in seconds between requests at which point this cache entry will be invalidated.
-        */
-       public SessionWayfCache(int expiration) {
-
-               if (expiration == 0) {
-                       this.expiration = 7200;
-               } else {
-                       this.expiration = expiration;
-               }
-       }
-
-       /**
-        * @see WayfCache#addHsToCache(HttpServletRequest)
-        */
-       public void addHsToCache(String handleService, HttpServletRequest req, HttpServletResponse res) {
-
-               HttpSession session = req.getSession(true);
-               session.setMaxInactiveInterval(expiration);
-               session.setAttribute("selectedHandleService", handleService);
-       }
-
-       /**
-        * @see WayfCache#deleteHsFromCache(HttpServletRequest)
-        */
-       public void deleteHsFromCache(HttpServletRequest req, HttpServletResponse res) {
-
-               HttpSession session = req.getSession(false);
-               if (session != null) {
-                       session.removeAttribute("selectedHandleService");
-               }
-       }
-
-       /**
-        * @see WayfCache#getCachedHS(HttpServletRequest)
-        */
-       public String getCachedHS(HttpServletRequest req) {
-
-               HttpSession session = req.getSession(false);
-               if (session == null) { return null; }
-               return (String) session.getAttribute("selectedHandleService");
-       }
-}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/WayfCache.java b/src/edu/internet2/middleware/shibboleth/wayf/WayfCache.java
deleted file mode 100755 (executable)
index 887cfac..0000000
+++ /dev/null
@@ -1,51 +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.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Defines a method for cacheing user selections regarding which shibboleth Handle Service should be used.
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-
-public interface WayfCache {
-
-       /**
-        * Add the specified Shibboleth Handle Service to the cache.
-        */
-       public void addHsToCache(String handleService, HttpServletRequest req, HttpServletResponse res);
-
-       /**
-        * Delete the Shibboleth Handle Service assoctiated with the current requester from the cache.
-        */
-       public void deleteHsFromCache(HttpServletRequest req, HttpServletResponse res);
-
-       /**
-        * Returns boolean indicator as to whether the current requester has a Handle Service entry in the cache.
-        */
-       public boolean hasCachedHS(HttpServletRequest req);
-
-       /**
-        * Retrieves the Handle Service associated with the current requester. Returns null if there is none currently
-        * associated.
-        */
-       public String getCachedHS(HttpServletRequest req);
-
-}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/WayfCacheBase.java b/src/edu/internet2/middleware/shibboleth/wayf/WayfCacheBase.java
deleted file mode 100755 (executable)
index 823fd4a..0000000
+++ /dev/null
@@ -1,40 +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.servlet.http.HttpServletRequest;
-
-/**
- * Shared implementation code for <code>WayfCache</code>.
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-public abstract class WayfCacheBase implements WayfCache {
-
-       /**
-        * @see WayfCache#getCachedHS(HttpServletRequest)
-        */
-       public boolean hasCachedHS(HttpServletRequest req) {
-
-               if (getCachedHS(req) == null) {
-                       return false;
-               } else {
-                       return true;
-               }
-       }
-
-}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/WayfCacheFactory.java b/src/edu/internet2/middleware/shibboleth/wayf/WayfCacheFactory.java
deleted file mode 100755 (executable)
index 3f1a82f..0000000
+++ /dev/null
@@ -1,49 +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 org.apache.log4j.Logger;
-
-/**
- * Factory for creating instances of <code>WayfCache</code> based on the state of the <code>WayfConfig</code>.
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-public class WayfCacheFactory {
-
-       private static Logger log = Logger.getLogger(WayfCacheFactory.class.getName());
-
-       public static WayfCache getInstance(String cacheType, WayfCacheOptions options) {
-
-               if (cacheType.equals("NONE")) {
-                       return new NullWayfCache();
-               } else if (cacheType.equals("SESSION")) {
-                       return new SessionWayfCache(options.getExpiration());
-               } else if (cacheType.equals("COOKIES")) {
-                       return new CookieWayfCache(options.getExpiration(), options.getDomain());
-               } else {
-                       log.warn("Invalid Cache type specified: running with cache type NONE.");
-                       return new NullWayfCache();
-               }
-       }
-
-       public static WayfCache getInstance(String cacheType) {
-
-               return getInstance(cacheType, new WayfCacheOptions());
-       }
-
-}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/WayfCacheOptions.java b/src/edu/internet2/middleware/shibboleth/wayf/WayfCacheOptions.java
deleted file mode 100755 (executable)
index d66efe3..0000000
+++ /dev/null
@@ -1,71 +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;
-
-/**
- * Runtime configuration bundle that is passed to a <code>WayfCacheFactory</code>.
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-public class WayfCacheOptions {
-
-       private int expiration;
-       private String domain;
-
-       /**
-        * Returns the domain.
-        * 
-        * @return String
-        */
-       public String getDomain() {
-
-               return domain;
-       }
-
-       /**
-        * Returns the expiration.
-        * 
-        * @return int
-        */
-       public int getExpiration() {
-
-               return expiration;
-       }
-
-       /**
-        * Sets the domain.
-        * 
-        * @param domain
-        *            The domain to set
-        */
-       public void setDomain(String domain) {
-
-               this.domain = domain;
-       }
-
-       /**
-        * Sets the expiration.
-        * 
-        * @param expiration
-        *            The expiration to set
-        */
-       public void setExpiration(int expiration) {
-
-               this.expiration = expiration;
-       }
-
-}
index 8c259da..c76c80d 100755 (executable)
@@ -19,6 +19,10 @@ package edu.internet2.middleware.shibboleth.wayf;
 import java.util.HashSet;
 
 import org.apache.log4j.Logger;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
 
 /**
  * Class used by the WAYF service to determine runtime options Most of the fields of this class should have reasonable
@@ -41,10 +45,97 @@ public class WayfConfig {
        private HashSet ignoredForMatch = new HashSet();
        private int cacheExpiration;
        private String cacheDomain;
-       private String cacheType = "COOKIES";
-
-       public WayfConfig() {
 
+       private String getValue(Element element, String what) throws ShibbolethConfigurationException
+       {
+               NodeList list = element.getElementsByTagName(what);
+           
+           if (list.getLength() > 0) {
+               if (list.getLength() > 1) {
+                       throw new ShibbolethConfigurationException("More than one <" + what + "/> element");
+               }
+                       
+               return list.item(0).getTextContent();
+           }
+           return null;
+       }
+       
+       /**
+        * 
+        * Parse the Supplied XML element into a new WayfConfig Object
+        * 
+        */
+       
+       public WayfConfig(Element config) throws ShibbolethConfigurationException {
+
+           if (!config.getTagName().equals("WayfConfig")) { 
+
+               throw new ShibbolethConfigurationException(
+                   "Unexpected configuration data.  <WayfConfig/> is needed."); 
+           }
+
+           log.debug("Loading global configuration properties.");
+
+           String raw = config.getAttribute("cacheDomain");
+
+           if ((raw != null) && (raw != "")) {
+               setCacheDomain(raw);
+           }
+               
+           raw = config.getAttribute("cacheExpiration");
+           if ((raw != null) && (raw != "")) {
+               
+               try {
+
+                       setCacheExpiration(Integer.parseInt(raw));
+               } catch (NumberFormatException ex) {
+                       
+                       throw new ShibbolethConfigurationException("Invalid CacheExpiration value - " + raw, ex);
+               }
+           }
+
+           raw = config.getAttribute("logoLocation");
+           if ((raw != null) && (raw != "")) {
+               
+               setLogoLocation(raw);
+           }
+           
+           raw = config.getAttribute("supportContact");
+           if ((raw != null) && (raw != "")) {
+               
+               setSupportContact(raw);
+           }
+           
+           raw = getValue(config, "HelpText");
+           
+           if ((raw != null) && (raw != "")) {
+                       
+               setHelpText(raw);
+           }
+
+           raw = getValue(config, "SearchResultEmptyText");
+           
+           if ((raw != null) && (raw != "")) {
+               
+               setSearchResultEmptyText(raw);
+           }
+           
+           NodeList list = config.getElementsByTagName("SearchIgnore");
+           
+           for (int i = 0; i < list.getLength(); i++ ) {
+               
+               NodeList inner = ((Element) list.item(i)).getElementsByTagName("IgnoreText");
+               
+               for(int j = 0; j < inner.getLength(); j++) {
+                       
+                       addIgnoredForMatch(inner.item(j).getTextContent());
+               }
+           }
+
+       }
+       
+       public WayfConfig()
+       {
                super();
        }
 
@@ -114,21 +205,6 @@ public class WayfConfig {
                ignoredForMatch.add(s.toLowerCase());
        }
 
-       public String getCacheType() {
-
-               return cacheType;
-       }
-
-       public void setCacheType(String cache) {
-
-               if (cache.toUpperCase().equals("NONE") || cache.toUpperCase().equals("SESSION")
-                               || cache.toUpperCase().equals("COOKIES")) {
-                       this.cacheType = cache.toUpperCase();
-               } else {
-                       log.warn("Cache type :" + cache + ": not recognized, using default.");
-               }
-       }
-
        /**
         * Returns the cacheDomain.
         * 
@@ -171,4 +247,4 @@ public class WayfConfig {
                this.cacheExpiration = cacheExpiration;
        }
 
-}
\ No newline at end of file
+}
diff --git a/src/edu/internet2/middleware/shibboleth/wayf/WayfConfigDigester.java b/src/edu/internet2/middleware/shibboleth/wayf/WayfConfigDigester.java
deleted file mode 100755 (executable)
index da1ecd6..0000000
+++ /dev/null
@@ -1,72 +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;
-
-/**
- * This class is a jakarta Digester style parser for the WAYF configuration file. It should populate the WayfConfig
- * object during WAYF initilization. NOTE: It is assumed that the mutators of this class will only be called by a single
- * thread during servlet initilization only (NOT thread safe)
- * 
- * @author Walter Hoehn wassa&#064;columbia.edu
- */
-
-public class WayfConfigDigester extends ServletDigester {
-
-       protected String wayfConfigClass = "edu.internet2.middleware.shibboleth.wayf.WayfConfig";
-       private boolean configured = false;
-
-       public WayfConfigDigester() {
-
-               super();
-               configure();
-       }
-
-       public WayfConfigDigester(SAXParser parser) {
-
-               super(parser);
-               configure();
-       }
-
-       public WayfConfigDigester(XMLReader reader) {
-
-               super(reader);
-               configure();
-       }
-
-       /**
-        * @see Digester#configure()
-        */
-       protected void configure() {
-
-               if (configured == true) { return; }
-               addObjectCreate("WayfConfig", wayfConfigClass);
-               addSetProperties("WayfConfig");
-               addCallMethod("WayfConfig/HelpText", "setHelpText", 0);
-               addCallMethod("WayfConfig/SearchResultEmptyText", "setSearchResultEmptyText", 0);
-               addCallMethod("WayfConfig/SearchIgnore/IgnoreText", "addIgnoredForMatch", 0);
-
-               configured = true;
-
-       }
-
-}
\ No newline at end of file
index 8e70d9e..86ff4a6 100755 (executable)
 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 java.util.Iterator;
 
+import javax.servlet.GenericServlet;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletException;
 import javax.servlet.UnavailableException;
@@ -30,13 +31,13 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.log4j.Logger;
-import org.xml.sax.SAXException;
+import org.w3c.dom.Document;
 
-import edu.internet2.middleware.shibboleth.common.ShibResource;
 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;
+import edu.internet2.middleware.shibboleth.metadata.provider.XMLMetadata;
+import edu.internet2.middleware.shibboleth.xml.Parser;
 
 /**
  * A servlet implementation of the Shibboleth WAYF service. Allows a browser
@@ -56,10 +57,6 @@ public class WayfService extends HttpServlet {
 
     private Metadata metadata;
 
-    private WayfCacheOptions wSessionOptions = new WayfCacheOptions();
-
-    private WayfCacheOptions wPermOptions = new WayfCacheOptions();
-
     private static Logger log = Logger.getLogger(WayfService.class.getName());
 
     /**
@@ -85,11 +82,6 @@ public class WayfService extends HttpServlet {
             throw new ServletException(e);
         }
 
-        // Setup Cacheing options
-        wSessionOptions.setDomain(config.getCacheDomain());
-        wPermOptions.setDomain(config.getCacheDomain());
-        wPermOptions.setExpiration(config.getCacheExpiration());
-
         initViewConfig();
         log.info("WAYF initialization completed.");
     }
@@ -98,19 +90,16 @@ public class WayfService extends HttpServlet {
      * Populates WayfConfig from file contents.
      */
     private void configure() throws UnavailableException {
-
         try {
-            InputStream is = new ShibResource(wayfConfigFileLocation, this.getClass()).getInputStream();
-            WayfConfigDigester digester = new WayfConfigDigester();
-            digester.setValidating(true);
-            config = (WayfConfig) digester.parse(is);
-
-        } catch (SAXException se) {
-            log.fatal("Error parsing WAYF configuration file.", se);
+            Document doc = Parser.loadDom(wayfConfigFileLocation, true);
+            config = new WayfConfig(doc.getDocumentElement());
+        } catch (IOException e) {
+            log.fatal("Error Loading WAYF configuration file.", e);
+            throw new UnavailableException("Error parsing WAYF configuration file.");
+        } catch (Exception e) {
+            // All other exceptions are from the parsing
+            log.fatal("Error parsing WAYF configuration file.", e);
             throw new UnavailableException("Error parsing WAYF configuration file.");
-        } catch (IOException ioe) {
-            log.fatal("Error reading WAYF configuration file.", ioe);
-            throw new UnavailableException("Error reading WAYF configuration file.");
         }
     }
 
@@ -170,16 +159,63 @@ public class WayfService extends HttpServlet {
         try {
             if (requestType.equals("deleteFromCache")) {
                 log.debug("Deleting saved HS from cache");
-                WayfCacheFactory.getInstance(config.getCacheType(), wPermOptions).deleteHsFromCache(req, res);
+                SamlIdPCookie.deleteCookie(req, res);
                 handleLookup(req, res);
-            } else if (WayfCacheFactory.getInstance(config.getCacheType()).hasCachedHS(req)) {
-                forwardToHS(req, res, WayfCacheFactory.getInstance(config.getCacheType()).getCachedHS(req));
-            } else if (requestType.equals("search")) {
+                return;
+            }
+
+            SamlIdPCookie cookie;
+            if (req.getParameter("nolookup") == null) {
+                cookie = SamlIdPCookie.getIdPCookie(req, res, config.getCacheDomain());
+            } else {
+                // For the test case, do not do a cache lookup, start as empty
+                cookie = new SamlIdPCookie(req, res, config.getCacheDomain());
+            }
+
+            if (requestType.equals("search")) {
                 handleSearch(req, res);
             } else if (requestType.equals("selection")) {
-                handleSelection(req, res);
+                String origin = req.getParameter("origin");
+                log.debug("Processing handle selection: " + origin);
+                if (origin == null) {
+                    handleLookup(req, res);
+                } else {
+                    if ((req.getParameter("cache") != null)) {
+                        if (req.getParameter("cache").equalsIgnoreCase("session")) {
+                            cookie.addIdPName(origin, 0);
+                        } else if (req.getParameter("cache").equalsIgnoreCase("perm")) {
+                            cookie.addIdPName(origin, config.getCacheExpiration());
+                        }
+                    }
+                    redirectToIdP(req, res, origin, cookie);
+                }
             } else {
-                handleLookup(req, res);
+                // Try for a cache hit
+                String idPName = null;
+                Iterator it = cookie.iterator();
+
+                //
+                // The cached data may contain several IdPs, some of which we do
+                // not know about
+                // so iterate down until we find one we do know about
+                //  
+                while (it.hasNext()) {
+                    idPName = (String) it.next();
+                    if (metadata.lookup(idPName) != null) {
+                        break;
+                    }
+                }
+
+                if (idPName != null) {
+                    //
+                    // move the name to the head of the list, preserving the
+                    // cache expiration
+                    //
+                    cookie.addIdPName(idPName, 0);
+                    redirectToIdP(req, res, idPName, cookie);
+                } else {
+                    handleLookup(req, res);
+                }
             }
         } catch (WayfException we) {
             handleError(req, res, we);
@@ -205,7 +241,7 @@ public class WayfService extends HttpServlet {
             }
 
             req.setAttribute("time", new Long(new Date().getTime() / 1000).toString()); // Unix
-                                                                                        // Time
+            // Time
             req.setAttribute("requestURL", req.getRequestURI().toString());
 
             log.debug("Displaying WAYF selection page.");
@@ -239,64 +275,51 @@ public class WayfService extends HttpServlet {
     /**
      * Registers a user's HS selection and forwards appropriately
      */
-    private void handleSelection(HttpServletRequest req, HttpServletResponse res) throws WayfException {
-
-        log.debug("Processing handle selection: " + req.getParameter("origin"));
-        String handleService = null;
+    private void redirectToIdP(HttpServletRequest req, HttpServletResponse res, String idPName, SamlIdPCookie cookie)
+            throws WayfException {
+        String idPSSOEndPoint = null;
         try {
             //
             // If we have had a refresh between then and now the following will
             // fail
             //
-            handleService = metadata.lookup(req.getParameter("origin")).getIDPSSODescriptor(
+            idPSSOEndPoint = metadata.lookup(idPName).getIDPSSODescriptor(
                     edu.internet2.middleware.shibboleth.common.XML.SHIB_NS).getSingleSignOnServiceManager()
                     .getDefaultEndpoint().getLocation();
         } catch (Exception ex) {
-            log.error("Error dispatching to IdP", ex);
+            //
+            // remove this entry (only) from the cache
+            //
+            cookie.deleteIdPName(idPName);
+            log.error("Error dispatching to IdP: ", ex);
         }
 
-        if (handleService == null) {
-            handleLookup(req, res);
-        } else {
-            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);
+        if (idPSSOEndPoint != null) {
+            log.info("Redirecting to SSO at selected IdP: " + idPSSOEndPoint);
+            try {
+                StringBuffer buffer = new StringBuffer(idPSSOEndPoint).append("?target=");
+                buffer.append(URLEncoder.encode(getTarget(req), "UTF-8")).append("&shire=");
+                buffer.append(URLEncoder.encode(getSHIRE(req), "UTF-8"));
+                String providerId = getProviderId(req);
+                log.debug("WALTER: (" + providerId + ").");
+                if (providerId != null) {
+                    buffer.append("&providerId=").append(URLEncoder.encode(getProviderId(req), "UTF-8"));
                 }
+                buffer.append("&time=").append(new Long(new Date().getTime() / 1000).toString()); // Unix
+                // Time
+                res.sendRedirect(buffer.toString());
+            } catch (IOException ioe) {
+                //
+                // remove this entry (only) from the cache
+                //
+                cookie.deleteIdPName(idPName);
+                throw new WayfException("Error forwarding to IdP SSO endpoint: " + ioe.toString());
             }
-            forwardToHS(req, res, handleService);
-        }
-
-    }
-
-    /**
-     * Uses an HTTP Status 307 redirect to forward the user the HS.
-     * 
-     * @param handleService The URL of the Shiboleth HS.
-     */
-    private void forwardToHS(HttpServletRequest req, HttpServletResponse res, String handleService)
-            throws WayfException {
-
-        log.info("Redirecting to selected Handle Service");
-        try {
-            StringBuffer buffer = new StringBuffer(handleService + "?target="
-                    + URLEncoder.encode(getTarget(req), "UTF-8") + "&shire="
-                    + URLEncoder.encode(getSHIRE(req), "UTF-8"));
-            String providerId = getProviderId(req);
-            log.debug("WALTER: (" + providerId + ").");
-            if (providerId != null) {
-                buffer.append("&providerId=" + URLEncoder.encode(getProviderId(req), "UTF-8"));
-            }
-            buffer.append("&time=" + new Long(new Date().getTime() / 1000).toString()); // Unix
-                                                                                        // Time
-            res.sendRedirect(buffer.toString());
-        } catch (IOException ioe) {
-            throw new WayfException("Error forwarding to HS: " + ioe.toString());
+        } else {
+            //
+            // We
+            handleLookup(req, res);
         }
-
     }
 
     /**
index 1ce23b7..8855860 100644 (file)
@@ -97,6 +97,7 @@ public class Parser {
             "urn:oasis:names:tc:SAML:1.0:protocol",
             "urn:mace:shibboleth:namemapper:1.0",
             "urn:mace:shibboleth:idp:config:1.0",
+            "urn:mace:shibboleth:wayf:config:1.0",
             "urn:mace:shibboleth:arp:1.0",
             "urn:mace:shibboleth:resolver:1.0",
             "urn:oasis:names:tc:SAML:2.0:metadata",
index fdff366..1bebc42 100755 (executable)
@@ -1,6 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- Schema for the Shibboleth WAYF Service configuration file - Walter Hoehn - 06/14/2002 -->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified">
+<xs:schema 
+       targetNamespace="urn:mace:shibboleth:wayf:config:1.0"
+       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
+       elementFormDefault="qualified">
         <xs:element name="WayfConfig" >
                 <xs:complexType>             
                        <xs:sequence>
@@ -16,7 +19,6 @@
                     </xs:sequence>
                     <xs:attribute name="supportContact" type="xs:string" use="optional"/>
                     <xs:attribute name="logoLocation" type="xs:string" use="optional"/>
-                    <xs:attribute name="cacheType" type="xs:string" use="optional"/>
                     <xs:attribute name="cacheExpiration" type="xs:string" use="optional"/>
                     <xs:attribute name="cacheDomain" type="xs:string" use="optional"/>
                 </xs:complexType>