SDSS WAYF patch for multi-federation support
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / wayf / WayfService.java
1 /*
2  * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package edu.internet2.middleware.shibboleth.wayf;
18
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.Hashtable;
22 import java.util.Iterator;
23 import java.util.List;
24 import javax.servlet.GenericServlet;
25 import javax.servlet.ServletException;
26 import javax.servlet.http.HttpServlet;
27 import javax.servlet.http.HttpServletRequest;
28 import javax.servlet.http.HttpServletResponse;
29
30 import org.apache.log4j.Logger;
31 import org.w3c.dom.Document;
32 import org.w3c.dom.Element;
33 import org.w3c.dom.NodeList;
34 import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
35 import edu.internet2.middleware.shibboleth.xml.Parser;
36
37 /**
38  * A servlet implementation of the Shibboleth WAYF service. Allows a browser
39  * user to select from among a group of origin sites. User selection is
40  * optionally cached and the user is forwarded to the HandleService appropriate
41  * to his selection.
42  * 
43  * @author Walter Hoehn wassa@columbia.edu
44  */
45 public class WayfService extends HttpServlet {
46
47         private String wayfConfigFileLocation;
48         private static final Logger log = Logger.getLogger(WayfService.class.getName());
49         
50         private List /*<DiscoveryServiceHandler>*/ discoveryServices = new ArrayList /*<DiscoveryServiceHandler>*/();
51         
52         /**
53          * @see GenericServlet#init()
54          */
55         public void init() throws ServletException {
56
57                 super.init();
58
59                 wayfConfigFileLocation = getServletContext().getInitParameter("WAYFConfigFileLocation");
60                 if (wayfConfigFileLocation == null) {
61                         wayfConfigFileLocation = getServletConfig().getInitParameter("WAYFConfigFileLocation");
62                 }
63                 if (wayfConfigFileLocation == null) {
64                         wayfConfigFileLocation = "/conf/wayfconfig.xml";
65                 }
66
67                 try {
68                         
69                         Document doc = Parser.loadDom(wayfConfigFileLocation, true);
70                         
71                         NodeList itemElements = doc.getDocumentElement().getElementsByTagNameNS(HandlerConfig.configNameSpace, "Default");
72                         
73                         HandlerConfig defaultHandlerConfig;
74                         
75                         if (itemElements.getLength() == 1) {
76                                 
77                                 Element element = (Element) itemElements.item(0);
78                                 String attribute = element.getAttribute("location");
79                                 
80                                 if (attribute != null && !attribute.equals("")) {
81                                         
82                                         log.error("<Default> element cannot contain a location attribute");
83                                         throw new ShibbolethConfigurationException("<Default> element cannot contain a location attribute");
84                                         
85                                 }
86
87                                 attribute = element.getAttribute("default");
88                                 
89                                 if (attribute != null && !attribute.equals("")) {
90
91                                         log.error("<Default> element cannot contain a default attribute");
92                                         throw new ShibbolethConfigurationException("<Default> element cannot contain a default attribute");
93                                         
94                                 }
95
96                                 itemElements = element.getElementsByTagName("Federation");
97                                 
98                                 if (itemElements.getLength() != 0) {
99                                         
100                                         log.error("<Default> element cannot contain <Federation> elements");
101                                         throw new ShibbolethConfigurationException("<Default> element cannot contain <Federation> elements");
102
103                                 }
104                                                         
105                                 defaultHandlerConfig = new HandlerConfig(element, new HandlerConfig());
106                         
107                         } else if (itemElements.getLength() == 0) {
108
109                                 defaultHandlerConfig = new HandlerConfig();
110                         
111                         } else {
112                                 log.error("Must specify exactly one <Default> element");
113                                 throw new ShibbolethConfigurationException("Must specify exactly one <Default> element");
114                         }
115                                                 
116                         //
117                         // Load metadata
118                         //
119                         Hashtable /*<String, IdPSiteSet>*/ siteSets = new Hashtable /*<String, IdPSiteSet>*/();
120
121                         itemElements = doc.getDocumentElement().getElementsByTagNameNS(HandlerConfig.configNameSpace,
122                                         "MetadataProvider");
123                         
124                         for (int i = 0; i < itemElements.getLength(); i++) {
125                                 
126                                 Element element = (Element) itemElements.item(i);
127                                 
128                                 IdPSiteSet siteset = new IdPSiteSet(element);
129                                 
130                                 siteSets.put(siteset.getIdentifier(), siteset);
131                         }
132                         if (siteSets.size() < 1) {
133                                 log.error("No Metadata Provider metadata loaded.");
134                                 throw new ShibbolethConfigurationException("Could not load SAML metadata.");
135                         }
136                         
137                         //
138                         // Load service handlers
139                         //
140                         itemElements = doc.getDocumentElement().getElementsByTagNameNS(HandlerConfig.configNameSpace,
141                                         "DiscoveryServiceHandler");
142                         
143                         for (int i = 0; i < itemElements.getLength(); i++) {
144                                 
145                                 discoveryServices.add(new DiscoveryServiceHandler((Element)itemElements.item(i), siteSets, defaultHandlerConfig));
146
147                         }
148                         //if ()
149
150                 } catch (IOException e) {
151                         if (log != null) {
152                                 log.fatal("Error Loading WAYF configuration file.", e);
153                         }
154                         throw new ServletException("Error Loading WAYF configuration file.", e);
155                 } catch (Exception e) {
156                         //
157                         // All other exceptions are from the parsing
158                         //
159                         if (log != null) {
160                                 log.fatal("Error parsing WAYF configuration file.", e);
161                         }
162                         throw new ServletException("Error parsing WAYF configuration file.", e);
163                 }
164                 
165                 log.info("WAYF initialization completed.");
166         }
167
168         /**
169          * @see HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
170          */
171         public void doGet(HttpServletRequest req, HttpServletResponse res) {
172
173                 
174                 log.info("Handling WAYF request.");
175                 // Tell the browser not to cache the WAYF page
176                 res.setHeader("Cache-Control", "no-cache");
177                 res.setHeader("Pragma", "no-cache");
178                 res.setDateHeader("Expires", 0);
179
180                 DiscoveryServiceHandler serviceHandler = lookupServiceHandler(req); 
181                 
182                 serviceHandler.doGet(req, res);
183                 
184         }
185
186         private DiscoveryServiceHandler lookupServiceHandler(HttpServletRequest req) {
187
188                 Iterator/*<DiscoveryServiceHandler>*/ it = discoveryServices.iterator();
189                 String requestURL = req.getRequestURL().toString(); 
190                 DiscoveryServiceHandler defaultHandler = null;
191                 
192                 while (it.hasNext()) {
193                         DiscoveryServiceHandler handler = (DiscoveryServiceHandler) it.next();
194                         
195                         if (requestURL.matches(handler.getLocation())) {
196                                 return handler;
197                         }
198                         if (defaultHandler == null || handler.isDefault()) {
199                                 defaultHandler = handler;
200                         }
201                 }
202                 log.warn("Could not find Discovery service Handler for " + requestURL);
203                 return defaultHandler;
204         }
205
206
207         
208 }