73287931a2efc5a32edeaf6bd11ea983317bfa9a
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / wayf / WayfService.java
1 package edu.internet2.middleware.shibboleth.wayf;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.net.URLEncoder;
6
7 import javax.servlet.RequestDispatcher;
8 import javax.servlet.ServletException;
9 import javax.servlet.UnavailableException;
10 import javax.servlet.http.HttpServlet;
11 import javax.servlet.http.HttpServletRequest;
12 import javax.servlet.http.HttpServletResponse;
13
14 import org.apache.log4j.Logger;
15 import org.xml.sax.SAXException;
16
17 /**
18  * A servlet implementation of the Shibboleth WAYF service.  Allows a browser user to 
19  * select from among a group of origin sites.  User selection is optionally cached 
20  * and the user is forwarded to the HandleService appropriate to his selection.
21  *
22  * @author Walter Hoehn wassa@columbia.edu
23  */
24
25 public class WayfService extends HttpServlet {
26
27         private String wayfConfigFileLocation;
28         private String siteConfigFileLocation;
29         private WayfConfig config;
30         private WayfOrigins originConfig;
31         private static Logger log = Logger.getLogger(WayfService.class.getName());
32
33         /**
34          * @see GenericServlet#init()
35          */
36         public void init() throws ServletException {
37
38                 super.init();
39                 log.info("Initializing WAYF.");
40                 loadInitParams();
41                 log.info("Loading configuration from file.");
42                 InputStream is = getServletContext().getResourceAsStream(wayfConfigFileLocation);
43                 WayfConfigDigester digester = new WayfConfigDigester(getServletContext());
44                 
45                 InputStream siteIs = getServletContext().getResourceAsStream(siteConfigFileLocation);
46                 OriginSitesDigester siteDigester = new OriginSitesDigester(getServletContext());
47                 
48                 try {
49                         //digester.setValidating(true);
50                         config = (WayfConfig) digester.parse(is);
51                         
52                         //siteDigester.setValidating(true);
53                         originConfig = (WayfOrigins) siteDigester.parse(siteIs);
54                         
55                         
56                 } catch (SAXException se) {
57                         log.fatal("Error parsing WAYF configuration file.", se);
58                         throw new UnavailableException("Error parsing WAYF configuration file.");
59                 } catch (IOException ioe) {
60                         log.fatal("Error reading WAYF configuration file.", ioe);
61                         throw new UnavailableException("Error reading WAYF configuration file.");
62                 }
63
64                 //Setup appliation-wide beans from config
65                 getServletContext().setAttribute("originsets", originConfig.getOriginSets());
66                 getServletContext().setAttribute("supportContact", config.getSupportContact());
67                 getServletContext().setAttribute("helpText", config.getHelpText());
68                 getServletContext().setAttribute("searchResultEmptyText", config.getSearchResultEmptyText());
69                 getServletContext().setAttribute("logoLocation", config.getLogoLocation());
70                 log.info("WAYF initialization completed.");
71         }
72
73         private void loadInitParams() {
74
75                 wayfConfigFileLocation = getServletConfig().getInitParameter("WAYFConfigFileLocation");
76                 if (wayfConfigFileLocation == null) {
77                         log.warn("No WAYFConfigFileLocation parameter found... using default location.");
78                         wayfConfigFileLocation = "/WEB-INF/conf/wayfconfig.xml";
79                 }
80                 siteConfigFileLocation = getServletConfig().getInitParameter("SiteConfigFileLocation");
81                 if (siteConfigFileLocation == null) {
82                         log.warn("No SiteonfigFileLocation parameter found... using default location.");
83                         siteConfigFileLocation = "/WEB-INF/conf/sites.xml";
84                 }
85
86         }
87
88         /**
89          * @see HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
90          */
91         public void doGet(HttpServletRequest req, HttpServletResponse res) {
92
93                 log.info("Handling WAYF request.");
94                 //Tell the browser not to cache the WAYF page
95                 res.setHeader("Cache-Control", "no-cache");
96                 res.setHeader("Pragma", "no-cache");
97                 res.setDateHeader("Expires", 0);
98                 
99                 //Decide how to route the request based on query string
100                 String requestType = req.getParameter("action");
101                 if (requestType == null) {
102                         requestType = "lookup";
103                 }
104                 try {
105                         if (requestType.equals("deleteFromCache")) {
106                                 log.debug("Deleting saved HS from cache");
107                                 WayfCacheFactory.getInstance(config.getCacheType()).deleteHsFromCache(req, res);
108                                 handleLookup(req, res);
109                         } else if (WayfCacheFactory.getInstance(config.getCacheType()).hasCachedHS(req)) {
110                                 handleRedirect(req, res, WayfCacheFactory.getInstance(config.getCacheType()).getCachedHS(req));
111                         } else if (requestType.equals("search")) {
112                                 handleSearch(req, res);
113                         } else if (requestType.equals("selection")) {
114                                 handleSelection(req, res);
115                         } else {
116                                 handleLookup(req, res);
117                         }
118                 } catch (WayfException we) {
119                         handleError(req, res, we);
120                 }
121         }
122
123         private void handleLookup(HttpServletRequest req, HttpServletResponse res) throws WayfException {
124
125                 if ((getSHIRE(req) == null) || (getTarget(req) == null)) {
126                         throw new WayfException("Invalid or missing data from SHIRE");
127                 }
128                 req.setAttribute("shire", getSHIRE(req));
129                 req.setAttribute("target", getTarget(req));
130                 req.setAttribute("encodedShire", URLEncoder.encode(getSHIRE(req)));
131                 req.setAttribute("encodedTarget", URLEncoder.encode(getTarget(req)));
132                 
133                 log.debug("Displaying WAYF selection page.");
134                 RequestDispatcher rd = req.getRequestDispatcher("/wayf.jsp");
135                 try {
136                         rd.forward(req, res);
137                 } catch (IOException ioe) {
138                         throw new WayfException("Problem displaying WAYF UI." + ioe.toString());
139                 } catch (ServletException se) {
140                         throw new WayfException("Problem displaying WAYF UI." + se.toString());
141                 }
142         }
143
144         private void handleSearch(HttpServletRequest req, HttpServletResponse res) throws WayfException {
145
146                 if (req.getParameter("string") != null) {
147                         Origin[] origins = originConfig.seachForMatchingOrigins(req.getParameter("string"), config);
148                         if (origins.length != 0) {
149                                 req.setAttribute("searchresults", origins);
150                         } else {
151                                 req.setAttribute("searchResultsEmpty", "true");
152                         }
153                 }
154                 handleLookup(req, res);
155
156         }
157
158         private void handleSelection(HttpServletRequest req, HttpServletResponse res) throws WayfException {
159
160                 String handleService = originConfig.lookupHSbyName(req.getParameter("origin"));
161                 if (handleService == null) {
162                         handleLookup(req, res);
163                 } else {
164                         WayfCacheFactory.getInstance(config.getCacheType()).addHsToCache(handleService, req, res);
165                         handleRedirect(req, res, handleService);
166                 }
167
168         }
169
170         private void handleRedirect(HttpServletRequest req, HttpServletResponse res, String handleService)
171                 throws WayfException {
172                 
173                 String shire = getSHIRE(req);
174                 String target = getTarget(req);
175                 log.info("Redirecting to selected Handle Service");
176                 try {
177                         res.sendRedirect(
178                                 handleService
179                                         + "?target="
180                                         + URLEncoder.encode(target)
181                                         + "&shire="
182                                         + URLEncoder.encode(shire));
183                 } catch (IOException ioe) {
184                         throw new WayfException("Error forwarding to HS: " + ioe.toString());
185                 }
186
187         }
188
189         private void handleError(HttpServletRequest req, HttpServletResponse res, WayfException we) {
190
191                 log.error("WAYF Failure: " + we.toString());
192                 log.debug("Displaying WAYF error page.");
193                 req.setAttribute("errorText", we.toString());
194                 req.setAttribute("requestURL", req.getRequestURI().toString());
195                 RequestDispatcher rd = req.getRequestDispatcher("/wayferror.jsp");
196
197                 try {
198                         rd.forward(req, res);
199                 } catch (IOException ioe) {
200                         log.error("Problem trying to display WAYF error page: " + ioe.toString());
201                 } catch (ServletException se) {
202                         log.error("Problem trying to display WAYF error page: " + se.toString());
203                 }
204         }
205
206         private String getSHIRE(HttpServletRequest req) throws WayfException {
207
208                 String shire = (String) req.getAttribute("shire");
209                 if (req.getParameter("shire") != null) {
210                         shire = req.getParameter("shire");
211                 }
212                 if (shire == null) {
213                         throw new WayfException("Invalid data from SHIRE: No acceptance URL received.");
214                 }
215                 return shire;
216         }
217
218         private String getTarget(HttpServletRequest req) throws WayfException {
219
220                 String target = (String) req.getAttribute("target");
221                 if (req.getParameter("target") != null) {
222                         target = req.getParameter("target");
223                 }
224                 if (target == null) {
225                         throw new WayfException("Invalid data from SHIRE: No target URL received.");
226                 }
227                 return target;
228         }
229
230 }