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

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

Adding in security capabilities for Greenstone 3

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