source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/LibraryServlet.java@ 25257

Last change on this file since 25257 was 25257, checked in by sjm84, 12 years ago

Various changes to support the new URLFilter and image captcha functionality

  • Property svn:keywords set to Author Date Id Revision
File size: 31.7 KB
Line 
1package org.greenstone.gsdl3;
2
3import org.greenstone.gsdl3.comms.*;
4import org.greenstone.gsdl3.core.*;
5import org.greenstone.gsdl3.service.Authentication;
6import org.greenstone.gsdl3.util.*;
7import org.greenstone.gsdl3.action.PageAction; // used to get the default action
8import org.w3c.dom.Document;
9import org.w3c.dom.Element;
10import org.w3c.dom.Node;
11import org.w3c.dom.NodeList;
12import java.io.*;
13import javax.servlet.*;
14import javax.servlet.http.*;
15
16import java.util.Enumeration;
17import java.util.ArrayList;
18import java.util.HashMap;
19import java.util.Iterator;
20import java.util.List;
21import java.util.Map;
22import java.lang.reflect.Type;
23import java.util.Hashtable;
24import org.apache.log4j.*;
25
26import com.google.gson.Gson;
27import com.google.gson.reflect.TypeToken;
28
29// Apache Commons
30import org.apache.commons.lang3.*;
31
32/**
33 * a servlet to serve the greenstone library - we are using servlets instead of
34 * cgi the init method is called only once - the first time the servlet classes
35 * are loaded. Each time a request comes in to the servlet, the session() method
36 * is called in a new thread (calls doGet/doPut etc) takes the a=p&p=home type
37 * args and builds a simple request to send to its receptionist, which returns a
38 * result in html, cos output=html is set in the request
39 *
40 * 18/Jul/07 xiao modify to make the cached parameters collection-specific. Most
41 * of the work is done in doGet(), except adding an inner class
42 * UserSessionCache.
43 *
44 * @see Receptionist
45 */
46public class LibraryServlet extends HttpServlet
47{
48
49 /** the receptionist to send messages to */
50 protected Receptionist recept = null;
51
52 /**
53 * the default language - is specified by setting a servlet param, otherwise
54 * DEFAULT_LANG is used
55 */
56 protected String default_lang = null;
57
58 /** Whether or not client-side XSLT support should be exposed */
59 protected boolean supports_client_xslt = false;
60
61 /**
62 * The default default - used if a default lang is not specified in the
63 * servlet params
64 */
65 protected final String DEFAULT_LANG = "en";
66
67 /** container Document to create XML Nodes */
68 protected Document doc = null;
69
70 /** a converter class to parse XML and create Docs */
71 protected XMLConverter converter = null;
72
73 /**
74 * the cgi stuff - the Receptionist can add new args to this
75 *
76 * its used by the servlet to determine what args to save
77 */
78 protected GSParams params = null;
79
80 /**
81 * user id - new one per session. This doesn't work if session state is
82 * saved between restarts - this requires this value to be saved too.
83 */
84 protected int next_user_id = 0;
85
86 /**
87 * a hash that contains all the active session IDs mapped to the cached
88 * items It is updated whenever the whole site or a particular collection is
89 * reconfigured using the command a=s&sa=c or a=s&sa=c&c=xxx It is in the
90 * form: sid -> (UserSessionCache object)
91 */
92 protected Hashtable session_ids_table = new Hashtable();
93
94 /**
95 * the maximum interval that the cached info remains in session_ids_table
96 * (in seconds) This is set in web.xml
97 */
98 protected int session_expiration = 1800;
99
100 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.LibraryServlet.class.getName());
101
102 /** initialise the servlet */
103 public void init(ServletConfig config) throws ServletException
104 {
105 // always call super.init;
106 super.init(config);
107 // disable preferences - does this work anyway??
108 //System.setProperty("java.util.prefs.PreferencesFactory", "org.greenstone.gsdl3.util.DisabledPreferencesFactory");
109
110 String library_name = config.getInitParameter(GSConstants.LIBRARY_NAME);
111 String gsdl3_home = config.getInitParameter(GSConstants.GSDL3_HOME);
112 String interface_name = config.getInitParameter(GSConstants.INTERFACE_NAME);
113
114 String allowXslt = (String) config.getInitParameter(GSConstants.ALLOW_CLIENT_SIDE_XSLT);
115 supports_client_xslt = allowXslt != null && allowXslt.equals("true");
116
117 this.default_lang = config.getInitParameter(GSConstants.DEFAULT_LANG);
118 String sess_expire = config.getInitParameter(GSXML.SESSION_EXPIRATION);
119
120 if (sess_expire != null && !sess_expire.equals(""))
121 {
122 this.session_expiration = Integer.parseInt(sess_expire);
123 }
124
125 if (library_name == null || interface_name == null)
126 {
127 // must have this
128 System.err.println("initialisation parameters not all set!");
129 System.err.println(" you must have libraryname and interfacename");
130 System.exit(1);
131 }
132
133 String site_name = config.getInitParameter(GSConstants.SITE_NAME);
134 String remote_site_name = null;
135 String remote_site_type = null;
136 String remote_site_address = null;
137
138 if (site_name == null)
139 {
140 // no site, try for communicator
141 remote_site_name = config.getInitParameter("remote_site_name");
142 remote_site_type = config.getInitParameter("remote_site_type");
143 remote_site_address = config.getInitParameter("remote_site_address");
144 if (remote_site_name == null || remote_site_type == null || remote_site_address == null)
145 {
146 System.err.println("initialisation paramters not all set!");
147 System.err.println("if site_name is not set, then you must have remote_site_name, remote_site_type and remote_site_address set");
148 System.exit(1);
149 }
150 }
151
152 if (this.default_lang == null)
153 {
154 // choose english
155 this.default_lang = DEFAULT_LANG;
156 }
157
158 HashMap config_params = new HashMap();
159
160 config_params.put(GSConstants.LIBRARY_NAME, library_name);
161 config_params.put(GSConstants.INTERFACE_NAME, interface_name);
162 config_params.put(GSConstants.ALLOW_CLIENT_SIDE_XSLT, supports_client_xslt);
163
164 if (site_name != null)
165 {
166 config_params.put(GSConstants.SITE_NAME, site_name);
167 }
168 this.converter = new XMLConverter();
169 this.doc = this.converter.newDOM();
170
171 // the receptionist -the servlet will talk to this
172 String recept_name = (String) config.getInitParameter("receptionist_class");
173 if (recept_name == null)
174 {
175 this.recept = new DefaultReceptionist();
176 }
177 else
178 {
179 try
180 {
181 this.recept = (Receptionist) Class.forName("org.greenstone.gsdl3.core." + recept_name).newInstance();
182 }
183 catch (Exception e)
184 { // cant use this new one, so use normal one
185 System.err.println("LibraryServlet configure exception when trying to use a new Receptionist " + recept_name + ": " + e.getMessage());
186 e.printStackTrace();
187 this.recept = new DefaultReceptionist();
188 }
189 }
190 this.recept.setConfigParams(config_params);
191
192 // the receptionist uses a MessageRouter or Communicator to send its requests to. We either create a MessageRouter here for the designated site (if site_name set), or we create a Communicator for a remote site. The is given to teh Receptionist, and the servlet never talks to it again.directly.
193 if (site_name != null)
194 {
195 String mr_name = (String) config.getInitParameter("messagerouter_class");
196 MessageRouter message_router = null;
197 if (mr_name == null)
198 { // just use the normal MR
199 message_router = new MessageRouter();
200 }
201 else
202 { // try the specified one
203 try
204 {
205 message_router = (MessageRouter) Class.forName("org.greenstone.gsdl3.core." + mr_name).newInstance();
206 }
207 catch (Exception e)
208 { // cant use this new one, so use normal one
209 System.err.println("LibraryServlet configure exception when trying to use a new MessageRouter " + mr_name + ": " + e.getMessage());
210 e.printStackTrace();
211 message_router = new MessageRouter();
212 }
213 }
214
215 message_router.setSiteName(site_name);
216 message_router.setLibraryName(library_name);
217 message_router.configure();
218 this.recept.setMessageRouter(message_router);
219 }
220 else
221 {
222 // talking to a remote site, create a communicator
223 Communicator communicator = null;
224 // we need to create the XML to configure the communicator
225 Element site_elem = this.doc.createElement(GSXML.SITE_ELEM);
226 site_elem.setAttribute(GSXML.TYPE_ATT, remote_site_type);
227 site_elem.setAttribute(GSXML.NAME_ATT, remote_site_name);
228 site_elem.setAttribute(GSXML.ADDRESS_ATT, remote_site_address);
229
230 if (remote_site_type.equals(GSXML.COMM_TYPE_SOAP_JAVA))
231 {
232 communicator = new SOAPCommunicator();
233 }
234 else
235 {
236 System.err.println("LibraryServlet.init Error: invalid Communicator type: " + remote_site_type);
237 System.exit(1);
238 }
239
240 if (!communicator.configure(site_elem))
241 {
242 System.err.println("LibraryServlet.init Error: Couldn't configure communicator");
243 System.exit(1);
244 }
245 this.recept.setMessageRouter(communicator);
246 }
247
248 // the params arg thingy
249
250 String params_name = (String) config.getInitParameter("params_class");
251 if (params_name == null)
252 {
253 this.params = new GSParams();
254 }
255 else
256 {
257 try
258 {
259 this.params = (GSParams) Class.forName("org.greenstone.gsdl3.util." + params_name).newInstance();
260 }
261 catch (Exception e)
262 {
263 System.err.println("LibraryServlet configure exception when trying to use a new params thing " + params_name + ": " + e.getMessage());
264 e.printStackTrace();
265 this.params = new GSParams();
266 }
267 }
268 // pass it to the receptionist
269 this.recept.setParams(this.params);
270 this.recept.configure();
271
272 //Allow the message router and the document to be accessed from anywhere in this servlet context
273 this.getServletContext().setAttribute("GSRouter", this.recept.getMessageRouter());
274 this.getServletContext().setAttribute("GSDocument", this.doc);
275 }
276
277 private void logUsageInfo(HttpServletRequest request)
278 {
279 String usageInfo = "";
280
281 //session-info: get params stored in the session
282 HttpSession session = request.getSession(true);
283 Enumeration attributeNames = session.getAttributeNames();
284 while (attributeNames.hasMoreElements())
285 {
286 String name = (String) attributeNames.nextElement();
287 usageInfo += name + "=" + session.getAttribute(name) + " ";
288 }
289
290 //logged info = general-info + session-info
291 usageInfo = request.getServletPath() + " " + //serlvet
292 "[" + request.getQueryString() + "]" + " " + //the query string
293 "[" + usageInfo.trim() + "]" + " " + // params stored in a session
294 request.getRemoteAddr() + " " + //remote address
295 request.getRequestedSessionId() + " " + //session id
296 request.getHeader("user-agent") + " "; //the remote brower info
297
298 logger.info(usageInfo);
299
300 }
301
302 public class UserSessionCache implements HttpSessionBindingListener
303 {
304
305 String session_id = "";
306
307 /**
308 * a hash that maps the session ID to a hashtable that maps the
309 * coll_name to its parameters coll_name -> Hashtable (param_name ->
310 * param_value)
311 */
312 protected Hashtable coll_name_params_table = null;
313
314 public UserSessionCache(String id, Hashtable table)
315 {
316 session_id = id;
317 coll_name_params_table = (table == null) ? new Hashtable() : table;
318 }
319
320 protected void cleanupCache(String coll_name)
321 {
322 if (coll_name_params_table.containsKey(coll_name))
323 {
324 coll_name_params_table.remove(coll_name);
325 }
326 }
327
328 protected Hashtable getParamsTable()
329 {
330 return coll_name_params_table;
331 }
332
333 public void valueBound(HttpSessionBindingEvent event)
334 {
335 // Do nothing
336 }
337
338 public void valueUnbound(HttpSessionBindingEvent event)
339 {
340 if (session_ids_table.containsKey(session_id))
341 {
342 session_ids_table.remove(session_id);
343 }
344 }
345
346 public int tableSize()
347 {
348 return (coll_name_params_table == null) ? 0 : coll_name_params_table.size();
349 }
350
351 }
352
353 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
354 {
355 logUsageInfo(request);
356
357 Map<String, String[]> queryMap = request.getParameterMap();
358 if (queryMap != null)
359 {
360 Iterator<String> queryIter = queryMap.keySet().iterator();
361 boolean redirect = false;
362 String href = null;
363 String rl = null;
364
365 while (queryIter.hasNext())
366 {
367 String q = queryIter.next();
368 if (q.equals("el"))
369 {
370 if ((queryMap.get(q)[0]).equals("direct"))
371 {
372 redirect = true;
373 }
374 }
375 else if (q.equals("href"))
376 {
377 href = queryMap.get(q)[0];
378 href = StringUtils.replace(href, "%2f", "/");
379 href = StringUtils.replace(href, "%7e", "~");
380 href = StringUtils.replace(href, "%3f", "?");
381 href = StringUtils.replace(href, "%3A", "\\:");
382 }
383 else if (q.equals("rl"))
384 {
385 rl = queryMap.get(q)[0];
386 }
387 }
388
389 //if query_string contains "el=", the web page will be redirected to the external URl, otherwise a greenstone page with an external URL will be displayed
390 //"rl=0" this is an external link
391 //"rl=1" this is an internal link
392 if ((redirect) && (href != null) && (rl.equals("0")))
393 {// This is an external link, the web page is re-directed to the external URL (&el=&rl=0&href="http://...")
394 response.setContentType("text/xml");
395 response.sendRedirect(href);
396 }
397 }
398
399 // Nested Diagnostic Configurator to identify the client for
400 HttpSession session = request.getSession(true);
401 session.setMaxInactiveInterval(session_expiration);
402 String uid = (String) session.getAttribute(GSXML.USER_ID_ATT);
403 if (uid == null)
404 {
405 uid = "" + getNextUserId();
406 session.setAttribute(GSXML.USER_ID_ATT, uid);
407 }
408
409 request.setCharacterEncoding("UTF-8");
410 response.setContentType("text/html;charset=UTF-8");
411 PrintWriter out = response.getWriter();
412
413 String lang = request.getParameter(GSParams.LANGUAGE);
414 if (lang == null || lang.equals(""))
415 {
416 // try the session cached lang
417 lang = (String) session.getAttribute(GSParams.LANGUAGE);
418 if (lang == null || lang.equals(""))
419 {
420 // still not set, use the default
421 lang = this.default_lang;
422 }
423 }
424 UserContext userContext = new UserContext();
425 userContext.setLanguage(lang);
426 userContext.setUserID(uid);
427
428 // set the lang in the session
429 session.setAttribute(GSParams.LANGUAGE, lang);
430
431 String output = request.getParameter(GSParams.OUTPUT);
432 if (output == null || output.equals(""))
433 {
434 output = "html"; // uses html by default
435 }
436
437 // If server output, force a switch to traditional interface
438 //output = (output.equals("server")) ? "html" : output;
439
440 // Force change the output mode if client-side XSLT is supported - server vs. client
441 // BUT only if the library allows client-side transforms
442 if (supports_client_xslt)
443 {
444 // MUST be done before the xml_message is built
445 Cookie[] cookies = request.getCookies();
446 Cookie xsltCookie = null;
447
448 // The client has cookies enabled and a value set - use it!
449 if (cookies != null)
450 {
451 for (Cookie c : cookies)
452 {
453 if (c.getName().equals("supportsXSLT"))
454 {
455 xsltCookie = c;
456 break;
457 }
458 }
459 output = (xsltCookie != null && xsltCookie.getValue().equals("true") && output.equals("html")) ? "xsltclient" : output;
460 }
461 }
462
463 // the request to the receptionist
464 Element xml_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
465 Element xml_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PAGE, "", userContext);
466 xml_request.setAttribute(GSXML.OUTPUT_ATT, output);
467
468 xml_message.appendChild(xml_request);
469
470 String action = request.getParameter(GSParams.ACTION);
471 String subaction = request.getParameter(GSParams.SUBACTION);
472 String collection = request.getParameter(GSParams.COLLECTION);
473 String document = request.getParameter(GSParams.DOCUMENT);
474 String service = request.getParameter(GSParams.SERVICE);
475
476 // We clean up the cache session_ids_table if system
477 // commands are issued (and also don't need to do caching for this request)
478 boolean should_cache = true;
479 if (action != null && action.equals(GSParams.SYSTEM))
480 {
481 should_cache = false;
482
483 // we may want to remove all collection cache info, or just a specific collection
484 boolean clean_all = true;
485 String clean_collection = null;
486 // system commands are to activate/deactivate stuff
487 // collection param is in the sc parameter.
488 // don't like the fact that it is hard coded here
489 String coll = request.getParameter(GSParams.SYSTEM_CLUSTER);
490 if (coll != null && !coll.equals(""))
491 {
492 clean_all = false;
493 clean_collection = coll;
494 }
495 else
496 {
497 // check other system types
498 if (subaction.equals("a") || subaction.equals("d"))
499 {
500 String module_name = request.getParameter("sn");
501 if (module_name != null && !module_name.equals(""))
502 {
503 clean_all = false;
504 clean_collection = module_name;
505 }
506 }
507 }
508 if (clean_all)
509 {
510 session_ids_table = new Hashtable();
511 session.removeAttribute(GSXML.USER_SESSION_CACHE_ATT);
512 }
513 else
514 {
515 // just clean up info for clean_collection
516 ArrayList cache_list = new ArrayList(session_ids_table.values());
517 for (int i = 0; i < cache_list.size(); i++)
518 {
519 UserSessionCache cache = (UserSessionCache) cache_list.get(i);
520 cache.cleanupCache(clean_collection);
521 }
522
523 }
524 }
525
526 // cache_key is the collection name, or service name
527 String cache_key = collection;
528 if (cache_key == null || cache_key.equals(""))
529 {
530 cache_key = service;
531 }
532
533 // logger.info("should_cache= " + should_cache);
534
535 //clear the collection-specific cache in the session, since we have no way to know whether this session is
536 //about the same collection as the last session or not.
537 Enumeration attributeNames = session.getAttributeNames();
538 while (attributeNames.hasMoreElements())
539 {
540 String name = (String) attributeNames.nextElement();
541 if (!name.equals(GSXML.USER_SESSION_CACHE_ATT) && !name.equals(GSParams.LANGUAGE) && !name.equals(GSXML.USER_ID_ATT))
542 {
543 session.removeAttribute(name);
544 }
545 }
546
547 UserSessionCache session_cache = null;
548 Hashtable param_table = null;
549 Hashtable table = null;
550 String sid = session.getId();
551 if (should_cache == true && cache_key != null && !cache_key.equals(""))
552 {
553 if (session_ids_table.containsKey(sid))
554 {
555 session_cache = (UserSessionCache) session_ids_table.get(sid);
556 param_table = session_cache.getParamsTable();
557 logger.info("collections in table: " + tableToString(param_table));
558 if (param_table.containsKey(cache_key))
559 {
560 //logger.info("existing table: " + collection);
561 table = (Hashtable) param_table.get(cache_key);
562 }
563 else
564 {
565 table = new Hashtable();
566 param_table.put(cache_key, table);
567 //logger.info("new table: " + collection);
568 }
569 }
570 else
571 {
572 param_table = new Hashtable();
573 table = new Hashtable();
574 param_table.put(cache_key, table);
575 session_cache = new UserSessionCache(sid, param_table);
576 session_ids_table.put(sid, session_cache);
577 session.setAttribute(GSXML.USER_SESSION_CACHE_ATT, session_cache);
578 //logger.info("new session id");
579 }
580 }
581
582 if (action == null || action.equals(""))
583 {
584 // should we do all the following stuff if using default page?
585 // display the home page - the default page
586 xml_request.setAttribute(GSXML.ACTION_ATT, "p");
587 xml_request.setAttribute(GSXML.SUBACTION_ATT, PageAction.HOME_PAGE);
588 }
589 else
590 {
591 xml_request.setAttribute(GSXML.ACTION_ATT, action);
592 if (subaction != null)
593 {
594 xml_request.setAttribute(GSXML.SUBACTION_ATT, subaction);
595 }
596
597 // create the param list for the greenstone request - includes
598 // the params from the current request and any others from the saved session
599 Element xml_param_list = this.doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
600 xml_request.appendChild(xml_param_list);
601
602 for (String name : queryMap.keySet())
603 {
604 if (!name.equals(GSParams.ACTION) && !name.equals(GSParams.SUBACTION) && !name.equals(GSParams.LANGUAGE) && !name.equals(GSParams.OUTPUT))
605 {// we have already dealt with these
606
607 String value = "";
608 String[] values = request.getParameterValues(name);
609 value = values[0];
610 if (values.length > 1)
611 {
612 for (int i = 1; i < values.length; i++)
613 {
614 value += "," + values[i];
615 }
616 }
617 // either add it to the param list straight away, or save it to the session and add it later
618 if (this.params.shouldSave(name) && table != null)
619 {
620 table.put(name, value);
621 }
622 else
623 {
624 Element param = this.doc.createElement(GSXML.PARAM_ELEM);
625 param.setAttribute(GSXML.NAME_ATT, name);
626 param.setAttribute(GSXML.VALUE_ATT, GSXML.xmlSafe(value));
627 xml_param_list.appendChild(param);
628 }
629 }
630 }
631 //put everything in the table into the session
632 // do we need to do this? why not just put from table into param list
633 if (table != null)
634 {
635 Enumeration keys = table.keys();
636 while (keys.hasMoreElements())
637 {
638 String name = (String) keys.nextElement();
639 session.setAttribute(name, (String) table.get(name));
640 }
641 }
642
643 // put in all the params from the session cache
644 Enumeration params = session.getAttributeNames();
645 while (params.hasMoreElements())
646 {
647 String name = (String) params.nextElement();
648
649 if (!name.equals(GSXML.USER_SESSION_CACHE_ATT) && !name.equals(GSParams.LANGUAGE) && !name.equals(GSXML.USER_ID_ATT))
650 {
651
652 // lang and uid are stored but we dont want it in the param list cos its already in the request
653 Element param = this.doc.createElement(GSXML.PARAM_ELEM);
654 param.setAttribute(GSXML.NAME_ATT, name);
655 String value = GSXML.xmlSafe((String) session.getAttribute(name));
656
657 // ugly hack to undo : escaping
658 value = StringUtils.replace(value, "%3A", "\\:");
659 param.setAttribute(GSXML.VALUE_ATT, value);
660 xml_param_list.appendChild(param);
661 }
662 }
663 }
664
665 if (!output.equals("html") && !output.equals("server") && !output.equals("xsltclient"))
666 {
667 response.setContentType("text/xml"); // for now use text
668 }
669
670 //Add custom HTTP headers if requested
671 String httpHeadersParam = request.getParameter(GSParams.HTTPHEADERFIELDS);
672 if (httpHeadersParam != null && httpHeadersParam.length() > 0)
673 {
674 Gson gson = new Gson();
675 Type type = new TypeToken<List<Map<String, String>>>()
676 {
677 }.getType();
678 List<Map<String, String>> httpHeaders = gson.fromJson(httpHeadersParam, type);
679 if (httpHeaders != null && httpHeaders.size() > 0)
680 {
681
682 for (int j = 0; j < httpHeaders.size(); j++)
683 {
684 Map nameValueMap = (Map) httpHeaders.get(j);
685 String name = (String) nameValueMap.get("name");
686 String value = (String) nameValueMap.get("value");
687
688 if (name != null && value != null)
689 {
690 response.setHeader(name, value);
691 }
692 }
693 }
694 }
695
696 String requestedURL = request.getRequestURL().toString();
697 String baseURL = requestedURL.substring(0, requestedURL.indexOf(this.getServletName()));
698 xml_request.setAttribute("baseURL", baseURL);
699 xml_request.setAttribute("remoteAddress", request.getRemoteAddr());
700
701 if(!runSecurityChecks(request, xml_request, userContext, out, baseURL, collection, document))
702 {
703 return;
704 }
705
706 Node xml_result = this.recept.process(xml_message);
707 encodeURLs(xml_result, response);
708 out.println(this.converter.getPrettyString(xml_result));
709
710 displaySize(session_ids_table);
711
712 } //end of doGet(HttpServletRequest, HttpServletResponse)
713
714 private boolean runSecurityChecks(HttpServletRequest request, Element xml_request, UserContext userContext, PrintWriter out, String baseURL, String collection, String document) throws ServletException
715 {
716 //Check if we need to login or logout
717 Map<String, String[]> params = request.getParameterMap();
718 String[] username = params.get("username");
719 String[] password = params.get("password");
720 String[] logout = params.get("logout");
721
722 if (logout != null)
723 {
724 request.logout();
725 }
726
727 if (username != null && password != null)
728 {
729 if (request.getAuthType() != null)
730 {
731 request.logout();
732 }
733
734 try
735 {
736 password[0] = Authentication.hashPassword(password[0]);
737 request.login(username[0], password[0]);
738 }
739 catch (Exception ex)
740 {
741 //The user entered in either the wrong username or the wrong password
742 Element loginPageMessage = this.doc.createElement(GSXML.MESSAGE_ELEM);
743 Element loginPageRequest = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PAGE, "", userContext);
744 loginPageRequest.setAttribute(GSXML.ACTION_ATT, "p");
745 loginPageRequest.setAttribute(GSXML.SUBACTION_ATT, "login");
746 loginPageRequest.setAttribute(GSXML.OUTPUT_ATT, "html");
747 loginPageRequest.setAttribute(GSXML.BASE_URL, baseURL);
748 loginPageMessage.appendChild(loginPageRequest);
749
750 Element paramList = this.doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
751 loginPageRequest.appendChild(paramList);
752
753 Element messageParam = this.doc.createElement(GSXML.PARAM_ELEM);
754 messageParam.setAttribute(GSXML.NAME_ATT, "loginMessage");
755 messageParam.setAttribute(GSXML.VALUE_ATT, "Either your username or password was incorrect, please try again.");
756 paramList.appendChild(messageParam);
757
758 Element urlParam = this.doc.createElement(GSXML.PARAM_ELEM);
759 urlParam.setAttribute(GSXML.NAME_ATT, "redirectURL");
760 String queryString = "";
761 if(request.getQueryString() != null)
762 {
763 queryString = "?" + request.getQueryString().replace("&", "&amp;");
764 }
765 urlParam.setAttribute(GSXML.VALUE_ATT, this.getServletName() + queryString);
766 paramList.appendChild(urlParam);
767
768 Node loginPageResponse = this.recept.process(loginPageMessage);
769 out.println(this.converter.getPrettyString(loginPageResponse));
770
771 return false;
772 }
773 }
774
775 //If a user is logged in
776 if (request.getAuthType() != null)
777 {
778 Element userInformation = this.doc.createElement(GSXML.USER_INFORMATION_ELEM);
779 userInformation.setAttribute("username", request.getUserPrincipal().getName());
780
781 Element userInfoMessage = this.doc.createElement(GSXML.MESSAGE_ELEM);
782 Element userInfoRequest = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_SECURITY, "GetUserInformation", userContext);
783 userInfoMessage.appendChild(userInfoRequest);
784
785 Element paramList = this.doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
786 userInfoRequest.appendChild(paramList);
787
788 Element param = this.doc.createElement(GSXML.PARAM_ELEM);
789 param.setAttribute(GSXML.NAME_ATT, GSXML.USERNAME_ATT);
790 param.setAttribute(GSXML.VALUE_ATT, request.getUserPrincipal().getName());
791 paramList.appendChild(param);
792
793 Element userInformationResponse = (Element) GSXML.getChildByTagName(this.recept.process(userInfoMessage), GSXML.RESPONSE_ELEM);
794 Element responseParamList = (Element) GSXML.getChildByTagName(userInformationResponse, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
795 if (responseParamList == null)
796 {
797 logger.error("Can't get the groups for user " + request.getUserPrincipal().getName());
798 }
799 else
800 {
801 HashMap responseParams = GSXML.extractParams(responseParamList, true);
802 String groups = (String) responseParams.get(GSXML.GROUPS_ATT);
803
804 userInformation.setAttribute(GSXML.GROUPS_ATT, groups);
805 xml_request.appendChild(userInformation);
806 }
807 }
808
809 //If we are in a collection-related page then make sure this user is allowed to access it
810 if (collection != null && !collection.equals(""))
811 {
812 //Get the security info for this collection
813 Element securityMessage = this.doc.createElement(GSXML.MESSAGE_ELEM);
814 Element securityRequest = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_SECURITY, collection, userContext);
815 securityMessage.appendChild(securityRequest);
816 if (document != null && !document.equals(""))
817 {
818 securityRequest.setAttribute(GSXML.NODE_OID, document);
819 }
820
821 Element securityResponse = (Element) GSXML.getChildByTagName(this.recept.process(securityMessage), GSXML.RESPONSE_ELEM);
822 ArrayList<String> groups = GSXML.getGroupsFromSecurityResponse(securityResponse);
823
824 //If guests are not allowed to access this page then check to see if the user is in a group that is allowed to access the page
825 if (!groups.contains(""))
826 {
827 boolean found = false;
828 for (String group : groups)
829 {
830 if (request.isUserInRole(group))
831 {
832 found = true;
833 break;
834 }
835 }
836
837 //The current user is not allowed to access the page so produce a login page
838 if (!found)
839 {
840 Element loginPageMessage = this.doc.createElement(GSXML.MESSAGE_ELEM);
841 Element loginPageRequest = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PAGE, "", userContext);
842 loginPageRequest.setAttribute(GSXML.ACTION_ATT, "p");
843 loginPageRequest.setAttribute(GSXML.SUBACTION_ATT, "login");
844 loginPageRequest.setAttribute(GSXML.OUTPUT_ATT, "html");
845 loginPageRequest.setAttribute(GSXML.BASE_URL, baseURL);
846 loginPageMessage.appendChild(loginPageRequest);
847
848 Element paramList = this.doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
849 loginPageRequest.appendChild(paramList);
850
851 Element messageParam = this.doc.createElement(GSXML.PARAM_ELEM);
852 messageParam.setAttribute(GSXML.NAME_ATT, "loginMessage");
853 if (request.getAuthType() == null)
854 {
855 messageParam.setAttribute(GSXML.VALUE_ATT, "Please log in to view this page");
856 }
857 else
858 {
859 messageParam.setAttribute(GSXML.VALUE_ATT, "You are not in the correct group to view this page, would you like to log in as a different user?");
860 }
861 paramList.appendChild(messageParam);
862
863 Element urlParam = this.doc.createElement(GSXML.PARAM_ELEM);
864 urlParam.setAttribute(GSXML.NAME_ATT, "redirectURL");
865 urlParam.setAttribute(GSXML.VALUE_ATT, this.getServletName() + "?" + request.getQueryString().replace("&", "&amp;"));
866 paramList.appendChild(urlParam);
867
868 Node loginPageResponse = this.recept.process(loginPageMessage);
869 out.println(this.converter.getPrettyString(loginPageResponse));
870
871 return false;
872 }
873 }
874 }
875 return true;
876 }
877
878 //a debugging method
879 private void displaySize(Hashtable table)
880 {
881 if (table == null)
882 {
883 logger.info("cached table is null");
884 return;
885 }
886 if (table.size() == 0)
887 {
888 logger.info("cached table size is zero");
889 return;
890 }
891 int num_cached_coll = 0;
892 ArrayList cache_list = new ArrayList(table.values());
893 for (int i = 0; i < cache_list.size(); i++)
894 {
895 num_cached_coll += ((UserSessionCache) cache_list.get(i)).tableSize();
896 }
897 logger.info("Number of sessions : total number of cached collection info = " + table.size() + " : " + num_cached_coll);
898 }
899
900 /** merely a debugging method! */
901 private String tableToString(Hashtable table)
902 {
903 String str = "";
904 Enumeration keys = table.keys();
905 while (keys.hasMoreElements())
906 {
907 String name = (String) keys.nextElement();
908 str += name + ", ";
909 }
910 return str;
911 }
912
913 /**
914 * this goes through each URL and adds in a session id if needed-- its
915 * needed if the browser doesn't accept cookies also escapes things if
916 * needed
917 */
918 protected void encodeURLs(Node dataNode, HttpServletResponse response)
919 {
920
921 if (dataNode == null)
922 {
923 return;
924 }
925
926 Element data = null;
927
928 short nodeType = dataNode.getNodeType();
929 if (nodeType == Node.DOCUMENT_NODE)
930 {
931 Document docNode = (Document) dataNode;
932 data = docNode.getDocumentElement();
933 }
934 else
935 {
936 data = (Element) dataNode;
937 }
938
939 if (data != null)
940 {
941
942 // get all the <a> elements
943 NodeList hrefs = data.getElementsByTagName("a");
944 // Instead of calculating each iteration...
945 int hrefscount = hrefs.getLength();
946
947 for (int i = 0; hrefs != null && i < hrefscount; i++)
948 {
949 Element a = (Element) hrefs.item(i);
950 // ugly hack to get rid of : in the args - interferes with session handling
951 String href = a.getAttribute("href");
952 if (!href.equals(""))
953 {
954 if (href.indexOf("?") != -1)
955 {
956 String[] parts = StringUtils.split(href, "\\?", -1);
957 if (parts.length == 1)
958 {
959 parts[0] = StringUtils.replace(parts[0], ":", "%3A");
960 href = "?" + parts[0];
961 }
962 else
963 {
964 parts[1] = StringUtils.replace(parts[1], ":", "%3A");
965 href = parts[0] + "?" + parts[1];
966 }
967
968 }
969 a.setAttribute("href", response.encodeURL(href));
970 }
971 }
972
973 // now find any submit bits - get all the <form> elements
974 NodeList forms = data.getElementsByTagName("form");
975 int formscount = forms.getLength();
976 for (int i = 0; forms != null && i < formscount; i++)
977 {
978 Element form = (Element) forms.item(i);
979 form.setAttribute("action", response.encodeURL(form.getAttribute("action")));
980 }
981 // are these the only cases where URLs occur??
982 // we should only do this for greenstone urls?
983 }
984
985 }
986
987 synchronized protected int getNextUserId()
988 {
989 next_user_id++;
990 return next_user_id;
991 }
992
993 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
994 {
995 doGet(request, response);
996 }
997}
Note: See TracBrowser for help on using the repository browser.