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

Last change on this file since 35290 was 35290, checked in by anupama, 3 years ago
  1. Use of groups local variable name in LibServlet method is confusing, as it's easy to read it as the list of groups a user member belongs to. Rather, it's any groups mentioned for a collection in its collConfig.xml's security elements and which security element groups will be checked against a (logged in) user's actual list of groups. 2. While working on updating DerbyWrapper to support extra table called ORIGROLES (extra column of origrole in ROLES table was the wrong idea), realised this was a long, roundabout and errorprone way as it requires lots of code changes to go about making the roles table's role column store the expanded groups instead of original user-entered groups. Instead, what we need is the reverse function of expandGroups(), contractExpandedgroups(), which will return any comma-separated list of groups to its most condense form that is probably closest to what the user entered, albeit with alphabetic reordering. This method can be called to do lazy evaluation to set UserTermInfo.origgroups when getOrigGroups() is called. The getOrigGroups() method will then be used as before by the GS3 admin/user account interface methods of Authentication.java (mainly Authentication.processAuthentication()), but Txt2UsersDB.java and ModifyUsersDB.java files will need to call getExpandedGroups() to store/retrieve these in the ROLES table. This will automatically be backwards compatible with earlier GS3 installation's userDBs.
  • Property svn:keywords set to Author Date Id Revision
File size: 44.1 KB
Line 
1/*
2 * LibraryServlet.java
3 * Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20package org.greenstone.gsdl3;
21
22import java.io.File;
23import java.io.IOException;
24import java.io.PrintWriter;
25import java.io.Serializable;
26import java.lang.reflect.Type;
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.Enumeration;
30import java.util.HashMap;
31import java.util.Hashtable;
32import java.util.Iterator;
33import java.util.List;
34import java.util.Map;
35
36import javax.servlet.ServletConfig;
37import javax.servlet.ServletContext;
38import javax.servlet.ServletException;
39import javax.servlet.http.Cookie;
40import javax.servlet.http.HttpServletRequest;
41import javax.servlet.http.HttpServletResponse;
42import javax.servlet.http.HttpSession;
43import javax.servlet.http.HttpSessionBindingEvent;
44import javax.servlet.http.HttpSessionBindingListener;
45
46import org.apache.commons.fileupload.FileItem;
47import org.apache.commons.fileupload.disk.DiskFileItemFactory;
48import org.apache.commons.fileupload.servlet.ServletFileUpload;
49import org.apache.commons.lang3.StringUtils;
50import org.apache.log4j.Logger;
51import org.greenstone.gsdl3.action.PageAction;
52import org.greenstone.gsdl3.comms.Communicator;
53import org.greenstone.gsdl3.comms.SOAPCommunicator;
54import org.greenstone.gsdl3.core.DefaultReceptionist;
55import org.greenstone.gsdl3.core.MessageRouter;
56import org.greenstone.gsdl3.core.Receptionist;
57import org.greenstone.gsdl3.service.Authentication;
58import org.greenstone.gsdl3.util.Dictionary;
59import org.greenstone.gsdl3.util.GSConstants;
60import org.greenstone.gsdl3.util.GSParams;
61import org.greenstone.gsdl3.util.GSXML;
62import org.greenstone.gsdl3.util.UserContext;
63import org.greenstone.gsdl3.util.XMLConverter;
64import org.greenstone.util.GlobalProperties;
65import org.json.JSONObject;
66import org.w3c.dom.Document;
67import org.w3c.dom.Element;
68import org.w3c.dom.Node;
69import org.w3c.dom.NodeList;
70
71import com.google.gson.Gson;
72import com.google.gson.reflect.TypeToken;
73
74/**
75 * a servlet to serve the greenstone library - we are using servlets instead of
76 * cgi
77 * the init method is called only once - the first time the servlet classes
78 * are loaded. Each time a request comes in to the servlet, the session() method
79 * is called in a new thread (calls doGet/doPut etc) takes the a=p&p=home type
80 * args and builds a simple request to send to its receptionist, which returns a
81 * result in html, cos output=html is set in the request
82 *
83 * 18/Jul/07 xiao modify to make the cached parameters collection-specific. Most
84 * of the work is done in doGet(), except adding an inner class
85 * UserSessionCache.
86 *
87 * @see Receptionist
88 */
89public class LibraryServlet extends BaseGreenstoneServlet
90{
91 protected static final String LOGIN_MESSAGE_PARAM = "loginMessage";
92 protected static final String REDIRECT_URL_PARAM = "redirectURL";
93 /** the receptionist to send messages to */
94 protected Receptionist recept = null;
95
96 /** We record the library name for later */
97 protected String library_name = null;
98 /** Whether or not client-side XSLT support should be exposed */
99 protected boolean supports_client_xslt = false;
100
101 /**
102 * the default language - is specified by setting a servlet param, otherwise
103 * DEFAULT_LANG is used
104 */
105 protected String default_lang = null;
106 /**
107 * The default default - used if a default lang is not specified in the
108 * servlet params
109 */
110 protected final String DEFAULT_LANG = "en";
111
112 /**
113 * the cgi stuff - the Receptionist can add new args to this
114 *
115 * its used by the servlet to determine what args to save,
116 * and to set default values
117 */
118 protected GSParams gs_params = null;
119
120 /**
121 * a hash that contains all the active session IDs mapped to the cached
122 * items It is updated whenever the whole site or a particular collection is
123 * reconfigured using the command a=s&sa=c or a=s&sa=c&c=xxx It is in the
124 * form: sid -> (UserSessionCache object)
125 */
126 protected Hashtable<String, UserSessionCache> session_ids_table = new Hashtable<String, UserSessionCache>();
127
128 /**
129 * the maximum interval that the cached info remains in session_ids_table
130 * (in seconds) This is set in web.xml
131 */
132 protected int session_expiration = 1800;
133
134 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.LibraryServlet.class.getName());
135
136 /** initialise the servlet */
137 public void init(ServletConfig config) throws ServletException
138 {
139 // always call super.init;
140 super.init(config);
141 // disable preferences - does this work anyway??
142 //System.setProperty("java.util.prefs.PreferencesFactory", "org.greenstone.gsdl3.util.DisabledPreferencesFactory");
143
144 // Look through all the init params
145 // these are the ones we are expecting
146 String interface_name = null;
147 String useXslt = null;
148 String sess_expire = null;
149 String site_name = null;
150 String recept_name = null;
151
152 // may have these instead of site_name
153 String remote_site_name = null;
154 String remote_site_type = null;
155 String remote_site_address = null;
156
157 // the stored config params
158 HashMap<String, Object> config_params = new HashMap<String, Object>();
159 Enumeration<String> params = config.getInitParameterNames();
160 while (params.hasMoreElements()) {
161 String name = params.nextElement();
162 String value = config.getInitParameter(name);
163 if (name.equals(GSConstants.LIBRARY_NAME)) {
164 library_name = value;
165 } else if (name.equals(GSConstants.INTERFACE_NAME)) {
166 interface_name = value;
167 } else if (name.equals(GSConstants.USE_CLIENT_SIDE_XSLT)) {
168 useXslt = value;
169 } else if (name.equals(GSConstants.DEFAULT_LANG)) {
170 this.default_lang = value;
171 } else if (name.equals(GSXML.SESSION_EXPIRATION)) {
172 sess_expire = value;
173 } else if (name.equals(GSConstants.SITE_NAME)) {
174 site_name = value;
175 } else if (name.equals(GSConstants.REMOTE_SITE_NAME)) {
176 remote_site_name = value;
177 } else if (name.equals(GSConstants.REMOTE_SITE_TYPE)) {
178 remote_site_type = value;
179 } else if (name.equals(GSConstants.REMOTE_SITE_ADDRESS)) {
180 remote_site_address = value;
181 } else if (name.equals(GSConstants.RECEPTIONIST_CLASS)) {
182 recept_name = value;
183 } else {
184 // If there is a param we are not expecting, just add to the list. That way users can add new servlet params which will go through to the XML source without modifying code.
185 config_params.put(name, value);
186 }
187 }
188 if (library_name == null || interface_name == null) {
189
190 // must have these
191 System.err.println("initialisation parameters not all set!");
192 System.err.println(" you must have libraryname and interfacename");
193 System.exit(1);
194 }
195
196 // If we don't have a site, then we must be using a Communicator, and all the remote params must be set
197 if (site_name == null && (remote_site_name == null || remote_site_type == null || remote_site_address == null)) {
198
199 System.err.println("initialisation paramters not all set!");
200 System.err.println("if site_name is not set, then you must have remote_site_name, remote_site_type and remote_site_address set");
201 System.exit(1);
202 }
203
204 supports_client_xslt = useXslt != null && useXslt.equals("true");
205 if (sess_expire != null && !sess_expire.equals(""))
206 {
207 this.session_expiration = Integer.parseInt(sess_expire);
208 }
209 if (this.default_lang == null)
210 {
211 // choose english
212 this.default_lang = DEFAULT_LANG;
213 }
214
215 config_params.put(GSConstants.LIBRARY_NAME, library_name);
216 config_params.put(GSConstants.INTERFACE_NAME, interface_name);
217 config_params.put(GSConstants.USE_CLIENT_SIDE_XSLT, supports_client_xslt);
218
219 if (site_name != null)
220 {
221 config_params.put(GSConstants.SITE_NAME, site_name);
222 }
223
224 // the receptionist -the servlet will talk to this
225 if (recept_name == null)
226 {
227 this.recept = new DefaultReceptionist();
228 }
229 else
230 {
231 try
232 {
233 this.recept = (Receptionist) Class.forName("org.greenstone.gsdl3.core." + recept_name).newInstance();
234 }
235 catch (Exception e)
236 { // cant use this new one, so use normal one
237 System.err.println("LibraryServlet configure exception when trying to use a new Receptionist " + recept_name + ": " + e.getMessage());
238 e.printStackTrace();
239 this.recept = new DefaultReceptionist();
240 }
241 }
242 this.recept.setConfigParams(config_params);
243
244 // the params arg thingy
245
246 String params_name = (String) config.getInitParameter("params_class");
247 if (params_name == null)
248 {
249 this.gs_params = new GSParams();
250 }
251 else
252 {
253 try
254 {
255 this.gs_params = (GSParams) Class.forName("org.greenstone.gsdl3.util." + params_name).newInstance();
256 }
257 catch (Exception e)
258 {
259 System.err.println("LibraryServlet configure exception when trying to use a new params thing " + params_name + ": " + e.getMessage());
260 e.printStackTrace();
261 this.gs_params = new GSParams();
262 }
263 }
264
265 // 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 the Receptionist, and the servlet never talks to it again directly.
266 if (site_name != null)
267 {
268 String mr_name = (String) config.getInitParameter("messagerouter_class");
269 MessageRouter message_router = null;
270 if (mr_name == null)
271 { // just use the normal MR
272 message_router = new MessageRouter();
273 }
274 else
275 { // try the specified one
276 try
277 {
278 message_router = (MessageRouter) Class.forName("org.greenstone.gsdl3.core." + mr_name).newInstance();
279 }
280 catch (Exception e)
281 { // cant use this new one, so use normal one
282 System.err.println("LibraryServlet configure exception when trying to use a new MessageRouter " + mr_name + ": " + e.getMessage());
283 e.printStackTrace();
284 message_router = new MessageRouter();
285 }
286 }
287
288 message_router.setSiteName(site_name);
289 message_router.setLibraryName(library_name);
290 message_router.setParams(this.gs_params);
291 message_router.configure();
292 this.recept.setMessageRouter(message_router);
293 }
294 else
295 {
296 // TODO: what do we do about params here?
297 // talking to a remote site, create a communicator
298 Communicator communicator = null;
299 // we need to create the XML to configure the communicator
300 Document doc = XMLConverter.newDOM();
301 Element site_elem = doc.createElement(GSXML.SITE_ELEM);
302 site_elem.setAttribute(GSXML.TYPE_ATT, remote_site_type);
303 site_elem.setAttribute(GSXML.NAME_ATT, remote_site_name);
304 site_elem.setAttribute(GSXML.ADDRESS_ATT, remote_site_address);
305
306 if (remote_site_type.equals(GSXML.COMM_TYPE_SOAP_JAVA))
307 {
308 communicator = new SOAPCommunicator();
309 }
310 else
311 {
312 System.err.println("LibraryServlet.init Error: invalid Communicator type: " + remote_site_type);
313 System.exit(1);
314 }
315
316 if (!communicator.configure(site_elem))
317 {
318 System.err.println("LibraryServlet.init Error: Couldn't configure communicator");
319 System.exit(1);
320 }
321 this.recept.setMessageRouter(communicator);
322 }
323
324 // pass params to the receptionist
325 this.recept.setParams(this.gs_params);
326 this.recept.configure();
327
328 //Allow the message router and the document to be accessed from anywhere in this servlet context
329 this.getServletContext().setAttribute(library_name+"Router", this.recept.getMessageRouter());
330 }
331
332 private void logUsageInfo(HttpServletRequest request, Map<String, String[]> queryMap)
333 {
334 String usageInfo = "";
335
336 //session-info: get params stored in the session
337 HttpSession session = request.getSession(true);
338 Enumeration attributeNames = session.getAttributeNames();
339 while (attributeNames.hasMoreElements())
340 {
341 String name = (String) attributeNames.nextElement();
342 usageInfo += name + "=" + session.getAttribute(name) + " ";
343 }
344
345 String queryParamStr = "";
346 if (queryMap != null)
347 {
348 Iterator<String> queryIter = queryMap.keySet().iterator();
349 while (queryIter.hasNext()) {
350 String q = queryIter.next();
351 String[] vals = queryMap.get(q);
352 queryParamStr += q +"="+StringUtils.join(vals, ",")+" ";
353 }
354 }
355 //logged info = general-info + session-info
356 usageInfo = request.getServletPath() + " " + //serlvet
357 "[" + queryParamStr.trim()+"]"+" " + // query map params
358 "session:[" + usageInfo.trim() + "]" + " " + // params stored in a session
359 request.getRemoteAddr() + " " + //remote address
360 request.getRequestedSessionId() + " " + //session id
361 request.getHeader("user-agent") + " "; //the remote brower info
362
363 logger.info(usageInfo);
364
365 }
366
367 public class UserSessionCache implements HttpSessionBindingListener
368 {
369 String session_id = "";
370
371 /**
372 * a hash that maps the session ID to a hashtable that maps the
373 * coll_name to its parameters coll_name -> Hashtable (param_name ->
374 * param_value)
375 */
376 protected Hashtable<String, Hashtable<String, String>> coll_name_params_table = null;
377
378 public UserSessionCache(String id, Hashtable<String, Hashtable<String, String>> table)
379 {
380 session_id = id;
381 coll_name_params_table = (table == null) ? new Hashtable() : table;
382 }
383
384 protected void cleanupCache(String coll_name)
385 {
386 if (coll_name_params_table.containsKey(coll_name))
387 {
388 coll_name_params_table.remove(coll_name);
389 }
390 }
391
392 protected Hashtable<String, Hashtable<String, String>> getParamsTable()
393 {
394 return coll_name_params_table;
395 }
396
397 public void valueBound(HttpSessionBindingEvent event)
398 {
399 // Do nothing
400 }
401
402 // if session cache id removed from session, this triggers this valueUnbound method on the value=this object
403 public void valueUnbound(HttpSessionBindingEvent event)
404 {
405 if (session_ids_table.containsKey(session_id))
406 {
407 session_ids_table.remove(session_id);
408 }
409 }
410
411 public int tableSize()
412 {
413 return (coll_name_params_table == null) ? 0 : coll_name_params_table.size();
414 }
415 }
416
417 public void destroy()
418 {
419 recept.cleanUp();
420 }
421
422 public void doGetOrPost(HttpServletRequest request, HttpServletResponse response, Map<String, String[]> queryMap) throws ServletException, IOException
423 {
424 logUsageInfo(request, queryMap);
425
426 if (processRedirectRequest(request, response, queryMap)) {
427 // this method will do the redirect if needed and return true if it has
428 // done so.
429 // e.g. el=direct/framed&rl=0&href=http://newurl.com
430 return;
431 }
432
433 // Nested Diagnostic Configurator to identify the client for
434 HttpSession session = request.getSession(true);
435 session.setMaxInactiveInterval(session_expiration);
436 String uid = session.getId();
437 request.setCharacterEncoding("UTF-8");
438 response.setContentType("text/html;charset=UTF-8");
439 PrintWriter out = response.getWriter();
440
441 String lang = getFirstParam(GSParams.LANGUAGE, queryMap);
442 if (lang == null || lang.equals(""))
443 {
444 // try the session cached lang
445 lang = (String) session.getAttribute(GSParams.LANGUAGE);
446 if (lang == null || lang.equals(""))
447 {
448 // still not set, use the default
449 lang = this.default_lang;
450 }
451 }
452
453 // set the lang in the session
454 session.setAttribute(GSParams.LANGUAGE, lang);
455
456 String output = getFirstParam(GSParams.OUTPUT, queryMap);
457 if (output == null || output.equals(""))
458 {
459 output = "html"; // uses html by default
460 }
461
462 String requestedURL = request.getRequestURL().toString();
463 String baseURL = "";
464 //logger.error("requested URL = "+requestedURL);
465 if (requestedURL.indexOf(library_name) != -1)
466 {
467 // we need to work out the baseURL and set it
468 baseURL = requestedURL;
469 int protocol_boundary_pos = baseURL.indexOf("://");
470 if (protocol_boundary_pos>=1) {
471 baseURL = baseURL.substring(protocol_boundary_pos+1); // change things like http:// or https:// to //
472 }
473 // The baseURL is everything up to the library_name.
474 // eg https://community.greenstone.org/greenstone3/library/collection/twso/page/about
475 // baseURL is //community.greenstone.org/greenstone3
476 // Issues: the library_name may occur in more than one place - eg if its part of the domain name mylibrary.heritage.nz/greenstone3/library
477 // or if a collection name is the same as the library name eg localhost:8585/greenstone3/twso/collection/twso/page/about.
478 // So can't just use teh first or last occurrence. Look for /library-name, and check its not the first position (eg //library.nzdl.org/greenstone3/library)
479 int library_name_index = baseURL.indexOf("/"+library_name);
480 if (library_name_index == 1) {
481 // we have library name at the start of the url - need to use the second one
482 library_name_index = baseURL.indexOf("/"+library_name, 2);
483 }
484 baseURL = baseURL.substring(0, library_name_index+1);
485 //logger.error("new base url = "+baseURL);
486
487 }
488
489 String fullURL;
490 if (request.getQueryString() != null)
491 {
492 fullURL = requestedURL + "?" + request.getQueryString();
493 }
494 else
495 {
496 fullURL = requestedURL;
497 }
498
499 UserContext userContext = new UserContext();
500 userContext.setLanguage(lang);
501 userContext.setUserID(uid);
502
503 if (!processLoginChanges(request, userContext, out, baseURL, queryMap, lang, output)) {
504 // any invalid login attempt will redirect to a new login page and return false
505 return;
506 }
507
508
509 if (request.getAuthType() != null)
510 {
511 // sets username, groups etc into usercontext
512 updateUserContextWithAuthenticatedInfo(request, userContext);
513 }
514
515 // If server output, force a switch to traditional interface
516 //output = (output.equals("server")) ? "html" : output;
517
518 // Force change the output mode if client-side XSLT is supported - server vs. client
519 // BUT only if the library allows client-side transforms
520 if (supports_client_xslt)
521 {
522 // MUST be done before the xml_message is built
523 Cookie[] cookies = request.getCookies();
524 Cookie xsltCookie = null;
525
526 // The client has cookies enabled and a value set - use it!
527 if (cookies != null)
528 {
529 for (Cookie c : cookies)
530 {
531 if (c.getName().equals("supportsXSLT"))
532 {
533 xsltCookie = c;
534 break;
535 }
536 }
537 output = (xsltCookie != null && xsltCookie.getValue().equals("true") && output.equals("html")) ? "xsltclient" : output;
538 }
539 }
540
541
542 String action = getFirstParam(GSParams.ACTION, queryMap);
543 String subaction = getFirstParam(GSParams.SUBACTION, queryMap);
544 String collection = getFirstParam(GSParams.COLLECTION, queryMap);
545 String document = getFirstParam(GSParams.DOCUMENT, queryMap);
546 String service = getFirstParam(GSParams.SERVICE, queryMap);
547 String specified_cache_key = getFirstParam(GSParams.CACHE_KEY, queryMap);
548
549 if (collection != null && !collection.equals("")) {
550 //is this user allowed to access this collection/document?
551 if (!runCollectionSecurityCheck(request, userContext, out, baseURL, collection, document, lang, output)) {
552 return;
553 }
554 }
555 // We clean up the cache session_ids_table if system
556 // commands are issued, and also don't need to do caching for these request requests
557 boolean should_cache = true;
558 if (action != null && action.equals(GSParams.SYSTEM_ACTION)
559 && !subaction.equals(GSXML.SYSTEM_TYPE_PING)
560 && !subaction.equals(GSXML.SYSTEM_TYPE_AUTHENTICATED_PING)) // don't 'clean' anything on a mere ping
561 {
562 should_cache = false;
563
564 // we may want to remove all collection cache info, or just a specific collection
565 boolean clean_all = true;
566 String clean_collection = null;
567 // system commands are to activate/deactivate stuff
568 // collection param is in the sc parameter.
569 // don't like the fact that it is hard coded here
570 String coll = getFirstParam(GSParams.SYSTEM_CLUSTER, queryMap);
571 if (coll != null && !coll.equals(""))
572 {
573 clean_all = false;
574 clean_collection = coll;
575 }
576 else
577 {
578 // check other system types
579 if (subaction.equals("a") || subaction.equals("d"))
580 {
581 String module_name = getFirstParam("sn", queryMap);
582 if (module_name != null && !module_name.equals(""))
583 {
584 clean_all = false;
585 clean_collection = module_name;
586 }
587 }
588 }
589 if (clean_all)
590 {
591 // TODO
592 session_ids_table = new Hashtable<String, UserSessionCache>();
593 session.removeAttribute(GSParams.USER_SESSION_CACHE); // triggers valueUnbound(), which removes the session id from the session_ids_table
594 }
595 else
596 {
597 // just clean up info for clean_collection
598 ArrayList<UserSessionCache> cache_list = new ArrayList<UserSessionCache>(session_ids_table.values());
599 for (int i = 0; i < cache_list.size(); i++)
600 {
601 UserSessionCache cache = cache_list.get(i);
602 cache.cleanupCache(clean_collection);
603 }
604
605 }
606 }
607
608 // cache_key is the collection name, or service name
609 String cache_key = specified_cache_key;
610 if (cache_key == null || cache_key.equals(""))
611 {
612 cache_key = collection;
613 }
614 if (cache_key == null || cache_key.equals(""))
615 {
616 cache_key = service;
617 }
618
619 //clear the collection-specific cache in the session, since we have no way to know whether this page is
620 //about the same collection as the last page or not.
621 Enumeration attributeNames = session.getAttributeNames();
622 while (attributeNames.hasMoreElements())
623 {
624 String name = (String) attributeNames.nextElement();
625 if (!name.equals(GSParams.USER_SESSION_CACHE) && !name.equals(GSParams.LANGUAGE) && !name.equals(GSXML.USER_ID_ATT) && !this.gs_params.isGlobal(name))
626 {
627 session.removeAttribute(name);
628 }
629 }
630
631 UserSessionCache session_cache = null;
632 Hashtable<String, Hashtable<String, String>> param_table = null;
633 Hashtable<String, String> table = null;
634 boolean new_table = false;
635 String sid = session.getId();
636 boolean new_session = false;
637 if (!session_ids_table.containsKey(sid)) {
638 new_session = true;
639 }
640 if (should_cache == true && cache_key != null && !cache_key.equals(""))
641 {
642 if (!new_session)
643 {
644 session_cache = session_ids_table.get(sid);
645 param_table = session_cache.getParamsTable();
646 if (param_table.containsKey(cache_key))
647 {
648 table = param_table.get(cache_key);
649 }
650 else
651 {
652 table = new Hashtable<String, String>();
653 param_table.put(cache_key, table);
654 new_table = true;
655 }
656 }
657 else
658 {
659
660 param_table = new Hashtable<String, Hashtable<String, String>>();
661 table = new Hashtable<String, String>();
662 param_table.put(cache_key, table);
663 session_cache = new UserSessionCache(sid, param_table);
664 session_ids_table.put(sid, session_cache);
665 session.setAttribute(GSParams.USER_SESSION_CACHE, session_cache);
666 new_table = true;
667 }
668
669 }
670
671 // here we add in default params values if need be - if we have a new session, or if we have a new table
672 // in an existing session
673 // don't override any existing values
674 if (new_session || new_table) {
675
676 Iterator i = this.gs_params.getParamsWithDefaults().iterator();
677 while (i.hasNext()) {
678 String p = (String)i.next();
679 String v = this.gs_params.getParamDefault(p);
680 if (this.gs_params.isGlobal(p)) {
681 //need to add in to session unless its already there
682 if (session.getAttribute(p) == null) {
683 session.setAttribute(p, v);
684 }
685 } else {
686 // add to table unless its already there
687 if (new_table && !table.containsKey(p)) {
688 table.put(p,v);
689 }
690 }
691
692 }
693 }
694
695 // the request to the receptionist
696 Document msg_doc = XMLConverter.newDOM();
697 Element xml_message = msg_doc.createElement(GSXML.MESSAGE_ELEM);
698 Element xml_request = GSXML.createBasicRequest(msg_doc, GSXML.REQUEST_TYPE_PAGE, "", userContext);
699 xml_request.setAttribute(GSXML.OUTPUT_ATT, output);
700
701 xml_message.appendChild(xml_request);
702
703 if (request.getAuthType() != null) {
704 // lots of classes are using the <userInformation> element. But all its info is now in userContext, so maybe we can get rid of this one day?
705 appendUserInformation(xml_request, userContext);
706 }
707
708 if (action == null || action.equals(""))
709 {
710 // display the home page - the default page
711 xml_request.setAttribute(GSXML.ACTION_ATT, "p");
712 xml_request.setAttribute(GSXML.SUBACTION_ATT, PageAction.HOME_PAGE);
713 }
714 else
715 {
716 xml_request.setAttribute(GSXML.ACTION_ATT, action);
717 if (subaction != null)
718 {
719 xml_request.setAttribute(GSXML.SUBACTION_ATT, subaction);
720 }
721 }
722
723 // create the param list for the greenstone request - includes
724 // the params from the current request and any others from the saved session
725 Element xml_param_list = msg_doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
726 xml_request.appendChild(xml_param_list);
727
728 if (queryMap.containsKey("s1.collection") || queryMap.containsKey("s1.group")){
729 table.remove("s1.collection");
730 table.remove("s1.group");
731 }
732 for (String name : queryMap.keySet())
733 {
734 if (!name.equals(GSParams.ACTION) && !name.equals(GSParams.SUBACTION) && !name.equals(GSParams.LANGUAGE) && !name.equals(GSParams.OUTPUT))
735 {// we have already dealt with these
736
737 String value = "";
738 String[] values = queryMap.get(name);
739 value = values[0];
740 if (values.length > 1)
741 {
742 for (int i = 1; i < values.length; i++)
743 {
744 value += "," + values[i];
745 }
746 }
747 // if we need to save the value, then add it to the session/cache table.
748 // otherwise add directly to the paramList
749 if (this.gs_params.shouldSave(name)) {
750 if (this.gs_params.isGlobal(name) || table == null) {
751 session.setAttribute(name, value);
752 } else {
753 table.put(name, value);
754 }
755 }
756 else
757 {
758 Element param = msg_doc.createElement(GSXML.PARAM_ELEM);
759 param.setAttribute(GSXML.NAME_ATT, name);
760 param.setAttribute(GSXML.VALUE_ATT, GSXML.xmlSafe(value));
761 if (this.gs_params.isSensitive(name)) {
762 param.setAttribute(GSXML.SENSITIVE_ATT, "true");
763 }
764 xml_param_list.appendChild(param);
765
766 }
767 }
768 }
769 //put everything in the table into the session
770 if (table != null)
771 {
772 Enumeration<String> keys = table.keys();
773 while (keys.hasMoreElements())
774 {
775 String name = keys.nextElement();
776 session.setAttribute(name, table.get(name));
777 }
778 }
779
780 // put in all the params from the session cache
781 Enumeration params = session.getAttributeNames();
782 while (params.hasMoreElements())
783 {
784 String name = (String) params.nextElement();
785 if (!name.equals(GSParams.USER_SESSION_CACHE) && !name.equals(GSParams.LANGUAGE) && !name.equals(GSXML.USER_ID_ATT))
786 {
787
788 // lang and uid are stored but we dont want it in the param list cos its already in the request
789 Element param = msg_doc.createElement(GSXML.PARAM_ELEM);
790 param.setAttribute(GSXML.NAME_ATT, name);
791 String value = GSXML.xmlSafe((String) session.getAttribute(name));
792
793 // ugly hack to undo : escaping
794 value = StringUtils.replace(value, "%3A", "\\:");
795 param.setAttribute(GSXML.VALUE_ATT, value);
796 xml_param_list.appendChild(param);
797 }
798 }
799
800
801 if (output.equals("json"))
802 {
803 response.setContentType("application/json");
804 }
805 else if (!output.equals("html") && !output.equals("server") && !output.equals("xsltclient"))
806 {
807 response.setContentType("text/xml"); // for now use text
808 }
809
810 //Add custom HTTP headers if requested
811 String httpHeadersParam = getFirstParam(GSParams.HTTP_HEADER_FIELDS, queryMap);
812 if (httpHeadersParam != null && httpHeadersParam.length() > 0)
813 {
814 Gson gson = new Gson();
815 Type type = new TypeToken<List<Map<String, String>>>()
816 {
817 }.getType();
818 List<Map<String, String>> httpHeaders = gson.fromJson(httpHeadersParam, type);
819 if (httpHeaders != null && httpHeaders.size() > 0)
820 {
821
822 for (int j = 0; j < httpHeaders.size(); j++)
823 {
824 Map nameValueMap = httpHeaders.get(j);
825 String name = (String) nameValueMap.get("name");
826 String value = (String) nameValueMap.get("value");
827
828 if (name != null && value != null)
829 {
830 response.setHeader(name, value);
831 }
832 }
833 }
834 }
835
836
837 xml_request.setAttribute("remoteAddress", request.getRemoteAddr());
838 xml_request.setAttribute("fullURL", fullURL.replace("&", "&amp;"));
839 xml_request.setAttribute("baseURL", baseURL);
840
841 logger.error("about to process this message");
842 logger.error(XMLConverter.getPrettyString(xml_message));
843 Node xml_result = this.recept.process(xml_message);
844 encodeURLs(xml_result, response);
845
846 String xml_string = XMLConverter.getPrettyString(xml_result);
847
848 if (output.equals("json"))
849 {
850 try
851 {
852 JSONObject json_obj = org.json.XML.toJSONObject(xml_string);
853
854 out.println(json_obj.toString());
855 }
856 catch (Exception e)
857 {
858 e.printStackTrace();
859 out.println("Error: failed to convert output XML to JSON format");
860 }
861 }
862 else
863 {
864 out.println(xml_string);
865 }
866
867 displaySize(session_ids_table);
868 }
869
870 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
871 {
872 doGetOrPost(request, response, request.getParameterMap());
873 } //end of doGet(HttpServletRequest, HttpServletResponse)
874
875 private boolean processRedirectRequest(HttpServletRequest request, HttpServletResponse response, Map<String, String[]> queryMap) throws IOException
876 {
877 if (queryMap != null)
878 {
879 Iterator<String> queryIter = queryMap.keySet().iterator();
880 boolean redirect = false;
881 String href = null;
882 String rl = null;
883 String el = null;
884 String collection = null;
885
886 while (queryIter.hasNext())
887 {
888 String q = queryIter.next();
889 if (q.equals(GSParams.COLLECTION))
890 {
891 collection = queryMap.get(q)[0];
892 }
893 else if (q.equals(GSParams.EXTERNAL_LINK_TYPE))
894 {
895 el = queryMap.get(q)[0];
896 }
897 else if (q.equals(GSParams.HREF))
898 {
899 href = queryMap.get(q)[0];
900 href = StringUtils.replace(href, "%2f", "/");
901 href = StringUtils.replace(href, "%7e", "~");
902 href = StringUtils.replace(href, "%3f", "?");
903 href = StringUtils.replace(href, "%3A", "\\:");
904 }
905 else if (q.equals(GSParams.RELATIVE_LINK))
906 {
907 rl = queryMap.get(q)[0];
908 }
909 }
910
911 //if query_string contains "el=direct", an href is specified, and its not a relative link, then the web page will be redirected to the external URl, otherwise a greenstone page with an external URL will be displayed
912 //"rl=0" this is an external link
913 //"rl=1" this is an internal link
914 if ((href != null) && (rl.equals("0")))
915 {// This is an external link,
916
917 if (el.equals("framed"))
918 {
919 // framed means we are linking to an external page inside our greenstone page
920 HttpSession session = request.getSession();
921 ServletContext context = session.getServletContext();
922 String new_url = context.getContextPath()+"/"+ library_name+"?a=p&sa=html&url="+href;
923 if (collection != null && !collection.equals("")) {
924 new_url += "&c="+collection;
925 }
926 response.sendRedirect(new_url);
927 }
928 else
929 {
930 // el = '' or direct
931 //the web page is re-directed to the external URL (&el=&rl=0&href="http://...")
932 response.sendRedirect(href);
933 }
934 return true;
935 }
936 }
937 return false;
938 }
939
940 private void generateLoginPage(String redirect_url_string, String error_message, UserContext userContext, PrintWriter out, String baseURL, String output) {
941
942 Document loginPageDoc = XMLConverter.newDOM();
943 Element loginPageMessage = loginPageDoc.createElement(GSXML.MESSAGE_ELEM);
944 Element loginPageRequest = GSXML.createBasicRequest(loginPageDoc, GSXML.REQUEST_TYPE_PAGE, "", userContext);
945 loginPageRequest.setAttribute(GSXML.ACTION_ATT, "p");
946 loginPageRequest.setAttribute(GSXML.SUBACTION_ATT, "login");
947 loginPageRequest.setAttribute(GSXML.OUTPUT_ATT, output);
948 loginPageRequest.setAttribute(GSXML.BASE_URL, baseURL);
949
950 loginPageMessage.appendChild(loginPageRequest);
951
952 Element paramList = loginPageDoc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
953 loginPageRequest.appendChild(paramList);
954
955 Element messageParam = loginPageDoc.createElement(GSXML.PARAM_ELEM);
956 messageParam.setAttribute(GSXML.NAME_ATT, LOGIN_MESSAGE_PARAM);
957 messageParam.setAttribute(GSXML.VALUE_ATT, error_message);
958 paramList.appendChild(messageParam);
959
960 Element urlParam = loginPageDoc.createElement(GSXML.PARAM_ELEM);
961 urlParam.setAttribute(GSXML.NAME_ATT, REDIRECT_URL_PARAM);
962
963 if (redirect_url_string.matches("^[a-z]+://.*$")) {
964 int protocol_boundary_pos = redirect_url_string.indexOf("://");
965 redirect_url_string = redirect_url_string.substring(protocol_boundary_pos+1); // change things like http:// or https:// to //
966 }
967
968 urlParam.setAttribute(GSXML.VALUE_ATT, redirect_url_string);
969 paramList.appendChild(urlParam);
970
971 Node loginPageResponse = this.recept.process(loginPageMessage);
972 out.println(XMLConverter.getPrettyString(loginPageResponse));
973 }
974
975 private boolean processLoginChanges(HttpServletRequest request, UserContext userContext, PrintWriter out, String baseURL, Map<String, String[]> queryMap, String lang, String output) throws ServletException {
976
977 logger.error("kk in processLoginChanges");
978 //Check if we need to login or logout
979 String username = getFirstParam(GSParams.USERNAME, queryMap);
980 String password = getFirstParam(GSParams.PASSWORD, queryMap);
981 String logout = getFirstParam(GSParams.LOGOUT, queryMap);
982
983 if (logout != null)
984 {
985 logger.error("plc logging out");
986 request.logout();
987 }
988
989 if (username != null && password != null)
990 {
991 logger.error("kk plc u&p not null");
992 //We are changing to another user, so log out first
993 if (request.getAuthType() != null)
994 {
995 logger.error("plc logging out 2");
996 request.logout();
997 }
998
999 //This try/catch block catches when the login request fails (e.g. The user enters an incorrect password).
1000 try
1001 {
1002 //Try a global login first
1003 password = Authentication.hashPassword(password);
1004 request.login(username, password);
1005 logger.error("plc logged in");
1006 }
1007 catch (Exception ex)
1008 {
1009 try
1010 {
1011 //If the global login fails then try a site-level login
1012 String siteName = (String) this.recept.getConfigParams().get(GSConstants.SITE_NAME);
1013 request.login(siteName + "-" + username, password);
1014 logger.error("plc logged in site wide");
1015 }
1016 catch (Exception exc)
1017 {
1018 //The user entered in either the wrong username or the wrong password
1019
1020 HttpSession session = request.getSession();
1021 ServletContext context = session.getServletContext();
1022 String redirect_url_string = request.getRequestURI().replaceFirst(context.getContextPath() + "/", "");
1023
1024 if ((request.getQueryString() != null) && (request.getQueryString().length() > 0))
1025 {
1026 redirect_url_string += "?" + request.getQueryString().replace("&", "&amp;");
1027 }
1028
1029 generateLoginPage(redirect_url_string, getTextString("auth.error.un_or_pw_err", lang), userContext, out, baseURL, output);
1030 return false;
1031 }
1032 }
1033 }
1034 return true;
1035
1036
1037 }
1038
1039 private void updateUserContextWithAuthenticatedInfo(HttpServletRequest request, UserContext userContext)
1040 {
1041 logger.error("in updateUserContext");
1042 //Get the username
1043 String user_name = request.getUserPrincipal().getName();
1044 userContext.setUsername(user_name);
1045 logger.error("setting username = "+request.getUserPrincipal().getName());
1046 //Get the groups for the user
1047 Document msg_doc = XMLConverter.newDOM();
1048 Element userInfoMessage = msg_doc.createElement(GSXML.MESSAGE_ELEM);
1049 Element userInfoRequest = GSXML.createBasicRequest(msg_doc, GSXML.REQUEST_TYPE_PROCESS, "GetUserInformation", userContext);
1050 userInfoMessage.appendChild(userInfoRequest);
1051
1052 Element paramList = msg_doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
1053 userInfoRequest.appendChild(paramList);
1054 paramList.appendChild(GSXML.createParameter(msg_doc, GSXML.USERNAME_ATT, user_name));
1055
1056 Element userInfoResponseMessage = (Element) this.recept.process(userInfoMessage);
1057 Element userInfoResponse = (Element) GSXML.getChildByTagName(userInfoResponseMessage, GSXML.RESPONSE_ELEM);
1058 Element respParamList = (Element) GSXML.getChildByTagName(userInfoResponse, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
1059
1060 if (respParamList != null)
1061 {
1062 HashMap<String, Serializable> params = GSXML.extractParams(respParamList, false);
1063 String groups = (String) params.get("groups");
1064 String editEnabled = (String) params.get("editEnabled");
1065 userContext.setGroups(groups.split(","));
1066 userContext.setEditEnabled((editEnabled != null) ? editEnabled : "false");
1067 }
1068 }
1069
1070 private void appendUserInformation(Element xml_request, UserContext userContext)
1071 {
1072 Element userInformation = xml_request.getOwnerDocument().createElement(GSXML.USER_INFORMATION_ELEM);
1073 userInformation.setAttribute(GSXML.USERNAME_ATT, userContext.getUsername());
1074
1075
1076 userInformation.setAttribute(GSXML.GROUPS_ATT, userContext.getGroupsString());
1077 userInformation.setAttribute(GSXML.EDIT_ENABLED_ATT, userContext.getEditEnabled());
1078 xml_request.appendChild(userInformation);
1079 }
1080
1081
1082 private boolean runCollectionSecurityCheck(HttpServletRequest request, UserContext userContext, PrintWriter out, String baseURL, String collection, String document, String lang, String output) {
1083 logger.error("kk in a coll"+collection);
1084 //Get the security info for this collection
1085 Document msg_doc = XMLConverter.newDOM();
1086 Element securityMessage = msg_doc.createElement(GSXML.MESSAGE_ELEM);
1087 Element securityRequest = GSXML.createBasicRequest(msg_doc, GSXML.REQUEST_TYPE_SECURITY, collection, userContext);
1088 securityMessage.appendChild(securityRequest);
1089 if (document != null && !document.equals(""))
1090 {
1091 securityRequest.setAttribute(GSXML.NODE_OID, document);
1092 }
1093
1094 Element securityResponse = (Element) GSXML.getChildByTagName(this.recept.process(securityMessage), GSXML.RESPONSE_ELEM);
1095 if (securityResponse == null)
1096 {
1097 return false;
1098 }
1099
1100 // Groups mentioned in collectionConfig.xml's Security element, se_groups
1101 ArrayList<String> se_groups = GSXML.getGroupsFromSecurityResponse(securityResponse);
1102
1103 //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
1104 if (!se_groups.contains(""))
1105 {
1106 boolean found = false;
1107 for (String se_group : se_groups)
1108 {
1109 if (request.isUserInRole(se_group))
1110 {
1111 found = true;
1112 break;
1113 }
1114 }
1115
1116 //The current user is not allowed to access the page so produce a login page
1117 if (!found)
1118 {
1119 logger.error("kk current user not allowed to access");
1120 String error_message = "";
1121 if (request.getAuthType() == null)
1122 {
1123 error_message = getTextString("auth.error.login", lang);
1124 }
1125 else
1126 {
1127 error_message = getTextString("auth.error.incorrect_login", lang);
1128 }
1129
1130 HttpSession session = request.getSession();
1131 ServletContext context = session.getServletContext();
1132 String redirect_url_string = request.getRequestURI().replaceFirst(context.getContextPath() + "/", "");
1133
1134 if (request.getQueryString() != null && request.getQueryString().length() > 0)
1135 {
1136 redirect_url_string += "?" + request.getQueryString().replace("&", "&amp;");
1137 }
1138
1139 generateLoginPage(redirect_url_string, error_message, userContext, out, baseURL, output);
1140 return false;
1141 }
1142 }
1143 return true;
1144 }
1145
1146 private String getTextString(String key, String lang) {
1147 return Dictionary.getTextString(key, lang, null, null, null, null, null);
1148
1149 }
1150 //a debugging method
1151 private void displaySize(Hashtable<String, UserSessionCache> table)
1152 {
1153 if (table == null)
1154 {
1155 //logger.info("cached table is null");
1156 return;
1157 }
1158 if (table.size() == 0)
1159 {
1160 //logger.info("cached table size is zero");
1161 return;
1162 }
1163 int num_cached_coll = 0;
1164 ArrayList<UserSessionCache> cache_list = new ArrayList<UserSessionCache>(table.values());
1165 for (int i = 0; i < cache_list.size(); i++)
1166 {
1167 num_cached_coll += cache_list.get(i).tableSize();
1168 }
1169 //logger.info("Number of sessions : total number of cached collection info = " + table.size() + " : " + num_cached_coll);
1170 }
1171
1172 /** merely a debugging method! */
1173 private String tableToString(Hashtable<String, Hashtable<String, String>> table)
1174 {
1175 String str = "";
1176 Enumeration<String> keys = table.keys();
1177 while (keys.hasMoreElements())
1178 {
1179 String name = keys.nextElement();
1180 str += name + ", ";
1181 }
1182 return str;
1183 }
1184
1185 /**
1186 * this goes through each URL and adds in a session id if needed-- its
1187 * needed if the browser doesn't accept cookies also escapes things if
1188 * needed
1189 */
1190 protected void encodeURLs(Node dataNode, HttpServletResponse response)
1191 {
1192 if (dataNode == null)
1193 {
1194 return;
1195 }
1196
1197 Element data = null;
1198
1199 short nodeType = dataNode.getNodeType();
1200 if (nodeType == Node.DOCUMENT_NODE)
1201 {
1202 Document docNode = (Document) dataNode;
1203 data = docNode.getDocumentElement();
1204 }
1205 else
1206 {
1207 data = (Element) dataNode;
1208 }
1209
1210 if (data != null)
1211 {
1212
1213 // get all the <a> elements
1214 NodeList hrefs = data.getElementsByTagName("a");
1215 // Instead of calculating each iteration...
1216 int hrefscount = hrefs.getLength();
1217
1218 for (int i = 0; hrefs != null && i < hrefscount; i++)
1219 {
1220 Element a = (Element) hrefs.item(i);
1221 // ugly hack to get rid of : in the args - interferes with session handling
1222 String href = a.getAttribute("href");
1223 if (!href.equals(""))
1224 {
1225 if (href.indexOf("?") != -1)
1226 {
1227 String[] parts = StringUtils.split(href, "\\?", -1);
1228 if (parts.length == 1)
1229 {
1230 parts[0] = StringUtils.replace(parts[0], ":", "%3A");
1231 href = "?" + parts[0];
1232 }
1233 else
1234 {
1235 parts[1] = StringUtils.replace(parts[1], ":", "%3A");
1236 href = parts[0] + "?" + parts[1];
1237 }
1238
1239 }
1240 a.setAttribute("href", response.encodeURL(href));
1241 }
1242 }
1243
1244 // now find any submit bits - get all the <form> elements
1245 NodeList forms = data.getElementsByTagName("form");
1246 int formscount = forms.getLength();
1247 for (int i = 0; forms != null && i < formscount; i++)
1248 {
1249 Element form = (Element) forms.item(i);
1250 form.setAttribute("action", response.encodeURL(form.getAttribute("action")));
1251 }
1252 // are these the only cases where URLs occur??
1253 // we should only do this for greenstone urls?
1254 }
1255
1256 }
1257
1258 protected String getFirstParam(String name, Map<String, String[]> map)
1259 {
1260 String[] val = map.get(name);
1261 if (val == null || val.length == 0)
1262 {
1263 return null;
1264 }
1265
1266 return val[0];
1267 }
1268
1269 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
1270 {
1271 //Check if we need to process a file upload
1272 if (ServletFileUpload.isMultipartContent(request))
1273 {
1274 DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
1275
1276 int sizeLimit = System.getProperties().containsKey("servlet.upload.filesize.limit") ? Integer.parseInt(System.getProperty("servlet.upload.filesize.limit")) : 100 * 1024 * 1024;
1277
1278 File tempDir = new File(GlobalProperties.getGSDL3Home() + File.separator + "tmp");
1279 if (!tempDir.exists())
1280 {
1281 tempDir.mkdirs();
1282 }
1283
1284 //We want all files to be stored on disk (hence the 0)
1285 fileItemFactory.setSizeThreshold(0);
1286 fileItemFactory.setRepository(tempDir);
1287
1288 ServletFileUpload uploadHandler = new ServletFileUpload(fileItemFactory);
1289 uploadHandler.setFileSizeMax(sizeLimit);
1290
1291 HashMap<String, String[]> queryMap = new HashMap<String, String[]>();
1292 try
1293 {
1294 List items = uploadHandler.parseRequest(request);
1295 Iterator iter = items.iterator();
1296 while (iter.hasNext())
1297 {
1298 FileItem current = (FileItem) iter.next();
1299 if (current.isFormField())
1300 {
1301 queryMap.put(current.getFieldName(), new String[] { current.getString() });
1302 }
1303 else if (current.getName() != null && !current.getName().equals(""))
1304 {
1305 File file = new File(tempDir, current.getName());
1306 current.write(file);
1307
1308 queryMap.put("md___ex.Filesize", new String[] { "" + file.length() });
1309 queryMap.put("md___ex.Filename", new String[] { "" + current.getName() });
1310 }
1311 }
1312 }
1313 catch (Exception e)
1314 {
1315 e.printStackTrace();
1316 }
1317
1318 doGetOrPost(request, response, queryMap);
1319 }
1320 else
1321 {
1322 doGetOrPost(request, response, request.getParameterMap());
1323 }
1324 }
1325}
Note: See TracBrowser for help on using the repository browser.