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

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

You can now specify a downloadFile argument in the URL to force the web browser to download a file, even if it is an image. Will need to add some form of security for this

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