Changeset 24019


Ignore:
Timestamp:
2011-05-17T13:20:56+12:00 (13 years ago)
Author:
sjm84
Message:

Added a new hhf (HTTP Header Fields) cgi parameter that can be used to specify items to be added to the responding header, for example hhf=Control-Cache%3Dno-cache to prevent the response from being cached by the browser

Location:
main/trunk/greenstone3/src/java/org/greenstone/gsdl3
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/LibraryServlet.java

    r23968 r24019  
    2323
    2424/** a servlet to serve the greenstone library - we are using servlets instead
    25  * of cgi
    26  * the init method is called only once - the first time the servlet classes
    27  * are loaded. Each time a request comes in to the servlet, the session()
    28  * method is called in a new thread (calls doGet/doPut etc)
    29  * takes the a=p&p=home type args and builds a simple request to send to
    30  * its receptionist, which returns a result in html, cos output=html
    31  * is set in the request
    32  *
    33  * 18/Jul/07 xiao
    34  * modify to make the cached parameters collection-specific.
    35  * Most of the work is done in doGet(), except adding an inner class UserSessionCache.
    36  *
    37  * @see Receptionist
    38  */
     25* of cgi
     26* the init method is called only once - the first time the servlet classes
     27* are loaded. Each time a request comes in to the servlet, the session()
     28* method is called in a new thread (calls doGet/doPut etc)
     29* takes the a=p&p=home type args and builds a simple request to send to
     30* its receptionist, which returns a result in html, cos output=html
     31* is set in the request
     32*
     33* 18/Jul/07 xiao
     34* modify to make the cached parameters collection-specific.
     35* Most of the work is done in doGet(), except adding an inner class UserSessionCache.
     36*
     37* @see Receptionist
     38*/
    3939public class LibraryServlet extends HttpServlet {
    40  
    41   /** the receptionist to send messages to */
    42   protected Receptionist recept=null;
    43 
    44   /** the default language - is specified by setting a servlet param,
    45    * otherwise DEFAULT_LANG is used*/
    46   protected String default_lang= null;
    47  
    48   /** Whether or not client-side XSLT support should be exposed */
    49   protected boolean supports_client_xslt = false;
    50 
    51   /** The default default - used if a default lang is not specified
    52    * in the servlet params */
    53   protected final String DEFAULT_LANG = "en";
    54 
    55   /** container Document to create XML Nodes */
    56   protected Document doc=null;
    57 
    58   /** a converter class to parse XML and create Docs */
    59   protected XMLConverter converter=null;
    60 
    61   /** the cgi stuff - the Receptionist can add new args to this
    62    *
    63    * its used by the servlet to determine what args to save */
    64   protected GSParams params = null;
    65  
    66   /** user id - new one per session. This doesn't work if session state is saved between restarts - this requires this value to be saved too. */
    67   protected int next_user_id = 0;
    68 
    69   /** a hash that contains all the active session IDs mapped to the cached items
    70    *  It is updated whenever the whole site or a particular collection is reconfigured
    71    *  using the command a=s&sa=c or a=s&sa=c&c=xxx
    72    *  It is in the form: sid -> (UserSessionCache object)
    73    */
    74   protected Hashtable session_ids_table = new Hashtable();
    75  
    76   /** the maximum interval that the cached info remains in session_ids_table (in seconds)
    77    *  This is set in web.xml
    78    */
    79   protected int session_expiration = 1800;
    80  
    81   static Logger logger = Logger.getLogger(org.greenstone.gsdl3.LibraryServlet.class.getName());
    82  
    83   /** initialise the servlet
    84    */
    85   public void init(ServletConfig config) throws ServletException {
    86     // always call super.init;
    87     super.init(config);
    88     // disable preferences - does this work anyway??
    89     //System.setProperty("java.util.prefs.PreferencesFactory", "org.greenstone.gsdl3.util.DisabledPreferencesFactory");
    90    
    91     String library_name = config.getInitParameter(GSConstants.LIBRARY_NAME);
    92     String gsdl3_home = config.getInitParameter(GSConstants.GSDL3_HOME);
    93     String interface_name = config.getInitParameter(GSConstants.INTERFACE_NAME);
    94    
    95     String allowXslt = (String)config.getInitParameter(GSConstants.ALLOW_CLIENT_SIDE_XSLT);
    96     supports_client_xslt = allowXslt != null && allowXslt.equals("true");
    97    
    98     this.default_lang = config.getInitParameter(GSConstants.DEFAULT_LANG);
    99     String sess_expire = config.getInitParameter(GSXML.SESSION_EXPIRATION);
    100    
    101     if (sess_expire != null && !sess_expire.equals("")) {
    102       this.session_expiration = Integer.parseInt(sess_expire);
    103     }
    104    
    105     if (library_name == null || interface_name ==null) {
    106       // must have this
    107       System.err.println("initialisation parameters not all set!");
    108       System.err.println(" you must have libraryname and interfacename");
    109       System.exit(1);
    110     }
    111    
    112     String site_name = config.getInitParameter(GSConstants.SITE_NAME);
    113     String remote_site_name = null;
    114     String remote_site_type = null;
    115     String remote_site_address = null;
    116    
    117     if (site_name == null) {
    118       // no site, try for communicator
    119       remote_site_name = config.getInitParameter("remote_site_name");
    120       remote_site_type = config.getInitParameter("remote_site_type");
    121       remote_site_address = config.getInitParameter("remote_site_address");
    122       if (remote_site_name == null || remote_site_type == null || remote_site_address == null) {
    123         System.err.println("initialisation paramters not all set!");
    124         System.err.println("if site_name is not set, then you must have remote_site_name, remote_site_type and remote_site_address set");
    125         System.exit(1);
    126       }
    127     }
    128    
    129     if (this.default_lang == null) {
    130       // choose english
    131       this.default_lang = DEFAULT_LANG;
    132     }
    133    
    134     HashMap config_params = new HashMap();
    135    
    136     config_params.put(GSConstants.LIBRARY_NAME, library_name);
    137     config_params.put(GSConstants.INTERFACE_NAME, interface_name); 
    138     config_params.put(GSConstants.ALLOW_CLIENT_SIDE_XSLT, supports_client_xslt);
    139    
    140     if (site_name != null) {
    141       config_params.put(GSConstants.SITE_NAME, site_name);
    142     }
    143     this.converter = new XMLConverter();
    144     this.doc = this.converter.newDOM();
    145    
    146     // the receptionist -the servlet will talk to this
    147     String recept_name = (String)config.getInitParameter("receptionist_class");
    148     if (recept_name == null) {
    149       this.recept = new DefaultReceptionist();
    150     } else {
    151       try {
    152         this.recept = (Receptionist)Class.forName("org.greenstone.gsdl3.core."+recept_name).newInstance();
    153       } catch (Exception e) { // cant use this new one, so use normal one
    154         System.err.println("LibraryServlet configure exception when trying to use a new Receptionist "+recept_name+": "+e.getMessage());
    155         e.printStackTrace();
    156         this.recept = new DefaultReceptionist();
    157       }
    158     }
    159     this.recept.setConfigParams(config_params);
    160    
    161     // 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.
    162     if (site_name != null) {
    163       String mr_name = (String)config.getInitParameter("messagerouter_class");
    164       MessageRouter message_router = null;
    165       if (mr_name == null) { // just use the normal MR
    166         message_router = new MessageRouter();
    167       } else { // try the specified one
    168         try {
    169           message_router = (MessageRouter)Class.forName("org.greenstone.gsdl3.core."+mr_name).newInstance();
    170         } catch (Exception e) { // cant use this new one, so use normal one
    171           System.err.println("LibraryServlet configure exception when trying to use a new MessageRouter "+mr_name+": "+e.getMessage());
    172           e.printStackTrace();
    173           message_router = new MessageRouter();
    174         }
    175       }
    176      
    177       message_router.setSiteName(site_name);
    178       message_router.setLibraryName(library_name);
    179       message_router.configure();
    180       this.recept.setMessageRouter(message_router);
    181     } else {
    182       // talking to a remote site, create a communicator
    183       Communicator communicator = null;
    184       // we need to create the XML to configure the communicator
    185       Element site_elem = this.doc.createElement(GSXML.SITE_ELEM);
    186       site_elem.setAttribute(GSXML.TYPE_ATT, remote_site_type);
    187       site_elem.setAttribute(GSXML.NAME_ATT, remote_site_name);
    188       site_elem.setAttribute(GSXML.ADDRESS_ATT, remote_site_address);
    189      
    190       if (remote_site_type.equals(GSXML.COMM_TYPE_SOAP_JAVA)) {
    191         communicator = new SOAPCommunicator();
    192       } else {
    193         System.err.println("LibraryServlet.init Error: invalid Communicator type: "+remote_site_type);
    194         System.exit(1);
    195       }
    196      
    197       if (!communicator.configure(site_elem)) {
    198         System.err.println("LibraryServlet.init Error: Couldn't configure communicator");
    199         System.exit(1);
    200       }
    201       this.recept.setMessageRouter(communicator);
    202     }
    203    
    204     // the params arg thingy
    205    
    206     String params_name = (String)config.getInitParameter("params_class");
    207     if (params_name == null) {
    208       this.params = new GSParams();
    209     } else {
    210       try {
    211         this.params = (GSParams)Class.forName("org.greenstone.gsdl3.util."+params_name).newInstance();
    212       } catch (Exception e) {
    213         System.err.println("LibraryServlet configure exception when trying to use a new params thing "+params_name+": "+e.getMessage());
    214         e.printStackTrace();
    215         this.params = new GSParams();
    216       }
    217     }
    218     // pass it to the receptionist
    219     this.recept.setParams(this.params);
    220     this.recept.configure();
    221    
    222   }
    223  
    224  
    225   private void logUsageInfo(HttpServletRequest request){
    226     String usageInfo = "";
    227    
    228     //session-info: get params stored in the session
    229     HttpSession session = request.getSession(true);
    230     Enumeration attributeNames = session.getAttributeNames();
    231     while(attributeNames.hasMoreElements()) {
    232       String name = (String)attributeNames.nextElement();
    233       usageInfo +=name+"="+session.getAttribute(name)+" ";
    234     }
    235    
    236     //logged info = general-info + session-info
    237     usageInfo =
    238       request.getServletPath()+" "+ //serlvet
    239       "["+request.getQueryString()+"]" +" "+ //the query string
    240       "["+usageInfo.trim()+"]" +" "+ // params stored in a session
    241       request.getRemoteAddr()+" "+   //remote address
    242       request.getRequestedSessionId()+" "+ //session id
    243       request.getHeader("user-agent")+" "; //the remote brower info
    244    
    245     logger.info(usageInfo);
    246    
    247   }
    248  
    249   public class UserSessionCache implements HttpSessionBindingListener {
    250 
    251     String session_id = "";
    252    
    253     /** a hash that maps the session ID to a hashtable that maps the coll_name to its parameters
    254      *  coll_name -> Hashtable (param_name -> param_value)
    255      */
    256     protected Hashtable coll_name_params_table = null;
    257    
    258     public UserSessionCache(String id, Hashtable table) {
    259       session_id = id;     
    260       coll_name_params_table = (table == null)? new Hashtable() : table;     
    261     }
    262 
    263     protected void cleanupCache(String coll_name) {
    264       if (coll_name_params_table.containsKey(coll_name)) {
    265         coll_name_params_table.remove(coll_name);
    266       }
    267     }
    268 
    269     protected Hashtable getParamsTable() {
    270       return coll_name_params_table;
    271     }
    272 
    273     public void valueBound(HttpSessionBindingEvent event) {
    274       // Do nothing
    275     }
    276 
    277     public void valueUnbound(HttpSessionBindingEvent event) {
    278       if(session_ids_table.containsKey(session_id)) {
    279         session_ids_table.remove(session_id);
    280       }
    281     }
    282 
    283     public int tableSize() {
    284       return (coll_name_params_table == null)? 0 : coll_name_params_table.size();
    285     }
    286 
    287   }
    288  
    289   public void doGet (HttpServletRequest request, HttpServletResponse response)
    290     throws ServletException, IOException {
    291     logUsageInfo (request);
    292 
    293     String query_string = request.getQueryString();
    294     if (query_string!=null){
    295       String[] query_arr = StringUtils.split(query_string, "&");
    296       boolean redirect = false;
    297       String href = null;
    298       String rl = null;
    299       String[] nameval = new String[2]; // Reuse it for memory efficiency purposes 
    300 
    301       for (int i=0;i<query_arr.length;i++){
    302 
    303         if (query_arr[i].startsWith("el=")){
    304           if (query_arr[i].substring(query_arr[i].indexOf("=")+1,query_arr[i].length()).equals("direct")){
    305             redirect = true;
    306           }
    307         }else if(query_arr[i].startsWith("href=")){
    308           href = query_arr[i].substring(query_arr[i].indexOf("=")+1,query_arr[i].length());
    309           href = StringUtils.replace(href, "%2f", "/");
    310           href = StringUtils.replace(href, "%7e", "~");
    311           href = StringUtils.replace(href, "%3f", "?");
    312           href = StringUtils.replace(href, "%3A", "\\:");
    313         }else if(query_arr[i].startsWith("rl=")){
    314           rl = query_arr[i].substring(query_arr[i].indexOf("=")+1,query_arr[i].length());
    315         }
    316       }
    317 
    318       //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
    319       //"rl=0" this is an external link
    320       //"rl=1" this is an internal link
    321       if ((redirect) && (href != null) && (rl.equals("0"))){// This is an external link, the web page is re-directed to the external URL (&el=&rl=0&href="http://...")
    322         response.setContentType("text/xml");
    323         response.sendRedirect(href);
    324       }
    325     }
    326    
    327     // Nested Diagnostic Configurator to identify the client for
    328     HttpSession session = request.getSession (true);
    329     session.setMaxInactiveInterval(session_expiration);
    330     String uid = (String)session.getAttribute (GSXML.USER_ID_ATT);
    331     if (uid ==null) {
    332       uid = ""+getNextUserId ();
    333       session.setAttribute (GSXML.USER_ID_ATT, uid);
    334     }
    335     request.setCharacterEncoding ("UTF-8");
    336     response.setContentType ("text/html;charset=UTF-8");
    337     PrintWriter out = response.getWriter ();
    338    
    339     String lang = request.getParameter (GSParams.LANGUAGE);
    340     if (lang==null || lang.equals ("")) {
    341       // try the session cached lang
    342       lang = (String)session.getAttribute (GSParams.LANGUAGE);
    343       if (lang==null || lang.equals ("")) {
    344         // still not set, use the default
    345         lang = this.default_lang;
    346       }
    347     }
    348    
    349     // set the lang in the session
    350     session.setAttribute (GSParams.LANGUAGE, lang);
    351    
    352     String output = request.getParameter (GSParams.OUTPUT);
    353     if (output==null || output.equals ("")) {
    354       output = "html"; // uses html by default
    355     }
    356    
    357     // If server output, force a switch to traditional interface
    358     //output = (output.equals("server")) ? "html" : output;
    359    
    360     // Force change the output mode if client-side XSLT is supported - server vs. client
    361     // BUT only if the library allows client-side transforms   
    362     if(supports_client_xslt) {
    363         // MUST be done before the xml_message is built
    364         Cookie[] cookies = request.getCookies();
    365         Cookie xsltCookie = null;
    366        
    367         // The client has cookies enabled and a value set - use it!
    368         if(cookies != null) {
    369             for(Cookie c : cookies) {
    370                 if(c.getName().equals("supportsXSLT")) {
    371                     xsltCookie = c;
    372                     break;
    373                 }
    374             }
    375             output = (xsltCookie != null && xsltCookie.getValue().equals("true") && output.equals("html")) ? "xsltclient" : output;
    376         }
    377     }
    378    
    379     // the request to the receptionist
    380     Element xml_message = this.doc.createElement (GSXML.MESSAGE_ELEM);
    381     Element xml_request = GSXML.createBasicRequest (this.doc, GSXML.REQUEST_TYPE_PAGE, "", lang, uid);
    382     xml_request.setAttribute (GSXML.OUTPUT_ATT, output);
    383    
    384     xml_message.appendChild (xml_request);
    385    
    386     String action = request.getParameter (GSParams.ACTION);
    387     String subaction = request.getParameter (GSParams.SUBACTION);
    388     String collection = request.getParameter(GSParams.COLLECTION);
    389     String service = request.getParameter(GSParams.SERVICE);
    390 
    391     // We clean up the cache session_ids_table if system
    392     // commands are issued (and also don't need to do caching for this request)
    393     boolean should_cache = true;
    394     if(action != null && action.equals(GSParams.SYSTEM)) {
    395       should_cache = false;
    396 
    397       // we may want to remove all collection cache info, or just a specific collection
    398       boolean clean_all = true;
    399       String clean_collection = null;
    400       // system commands are to activate/deactivate stuff
    401       // collection param is in the sc parameter.
    402       // don't like the fact that it is hard coded here
    403       String coll = request.getParameter(GSParams.SYSTEM_CLUSTER);
    404       if (coll != null && !coll.equals("")) {
    405         clean_all = false;
    406         clean_collection = coll;
    407       } else {
    408         // check other system types
    409         if (subaction.equals("a") || subaction.equals("d")) {
    410           String module_name = request.getParameter("sn");
    411           if (module_name != null && !module_name.equals("")) {
    412             clean_all = false;
    413             clean_collection = module_name;
    414           }
    415         }
    416       }
    417       if (clean_all) {
    418         session_ids_table = new Hashtable();
    419         session.removeAttribute(GSXML.USER_SESSION_CACHE_ATT);
    420       } else {
    421         // just clean up info for clean_collection
    422         ArrayList cache_list = new ArrayList(session_ids_table.values());
    423         for (int i=0; i<cache_list.size(); i++) {
    424           UserSessionCache cache = (UserSessionCache)cache_list.get(i);
    425           cache.cleanupCache(clean_collection);
    426         }
    427    
    428       }
    429 
    430     }
    431    
    432     // cache_key is the collection name, or service name
    433     String cache_key = collection;
    434     if (cache_key == null || cache_key.equals("")) {
    435       cache_key = service;
    436     }
    437    
    438     // logger.info("should_cache= " + should_cache);
    439 
    440     //clear the collection-specific cache in the session, since we have no way to know whether this session is
    441     //about the same collection as the last session or not.
    442     Enumeration attributeNames = session.getAttributeNames();
    443     while(attributeNames.hasMoreElements()) {
    444       String name = (String)attributeNames.nextElement();
    445       if (!name.equals (GSXML.USER_SESSION_CACHE_ATT)
    446         && !name.equals (GSParams.LANGUAGE)
    447         && !name.equals (GSXML.USER_ID_ATT)) {
    448 
    449         session.removeAttribute(name);
    450       }
    451     }
    452        
    453     UserSessionCache session_cache = null;
    454     Hashtable param_table = null;   
    455     Hashtable table = null;
    456     String sid = session.getId();
    457     if (should_cache == true && cache_key != null && !cache_key.equals("")) {
    458       if (session_ids_table.containsKey(sid)) {
    459         session_cache = (UserSessionCache)session_ids_table.get(sid);
    460         param_table = session_cache.getParamsTable();
    461         logger.info("collections in table: " + tableToString(param_table));
    462         if (param_table.containsKey(cache_key)) {
    463           //logger.info("existing table: " + collection);
    464           table = (Hashtable)param_table.get(cache_key);
    465         } else {
    466           table = new Hashtable();
    467           param_table.put(cache_key, table);
    468           //logger.info("new table: " + collection);
    469         }
    470       } else {
    471         param_table = new Hashtable();
    472         table = new Hashtable();
    473         param_table.put(cache_key, table);
    474         session_cache = new UserSessionCache(sid, param_table);
    475         session_ids_table.put(sid, session_cache);
    476         session.setAttribute(GSXML.USER_SESSION_CACHE_ATT, session_cache);
    477         //logger.info("new session id");
    478       }
    479     }
    480 
    481     if (action==null || action.equals ("")) {
    482       // should we do all the following stuff if using default page?
    483       // display the home page  - the default page
    484       xml_request.setAttribute (GSXML.ACTION_ATT, "p");
    485       xml_request.setAttribute (GSXML.SUBACTION_ATT, PageAction.HOME_PAGE);
    486     }
    487     else {
    488       xml_request.setAttribute (GSXML.ACTION_ATT, action);
    489       if (subaction != null) {
    490         xml_request.setAttribute (GSXML.SUBACTION_ATT, subaction);
    491       }
    492      
    493       //  create the param list for the greenstone request - includes
    494       // the params from the current request and any others from the saved session
    495       Element xml_param_list = this.doc.createElement (GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
    496       xml_request.appendChild (xml_param_list);
    497      
    498       Enumeration params = request.getParameterNames ();
    499       while(params.hasMoreElements ()) {
    500         String name = (String)params.nextElement ();
    501         if (!name.equals (GSParams.ACTION)
    502           && !name.equals (GSParams.SUBACTION)
    503           && !name.equals (GSParams.LANGUAGE)
    504           && !name.equals (GSParams.OUTPUT)) {// we have already dealt with these
    505          
    506           String value="";
    507           String [] values = request.getParameterValues (name);
    508           value = values[0];
    509           if (values.length > 1) {
    510             for (int i=1; i< values.length; i++) {
    511               value += ","+values[i];
    512             }
    513           }
    514           // either add it to the param list straight away, or save it to the session and add it later
    515           if (this.params.shouldSave (name) && table != null) {
    516             table.put(name, value);
    517           } else {
    518             Element param = this.doc.createElement (GSXML.PARAM_ELEM);
    519             param.setAttribute (GSXML.NAME_ATT, name);
    520             param.setAttribute (GSXML.VALUE_ATT, GSXML.xmlSafe (value));
    521             xml_param_list.appendChild (param);
    522           }
    523         }
    524       }
    525       //put everything in the table into the session
    526       // do we need to do this? why not just put from table into param list
    527       if (table != null) {
    528         Enumeration keys = table.keys ();
    529         while(keys.hasMoreElements ()) {
    530           String name = (String)keys.nextElement();
    531           session.setAttribute(name, (String)table.get(name));
    532         }
    533       }
    534      
    535       // put in all the params from the session cache
    536       params = session.getAttributeNames ();
    537       while(params.hasMoreElements ()) {
    538         String name = (String)params.nextElement ();
    539        
    540         if ( !name.equals (GSXML.USER_SESSION_CACHE_ATT)
    541           && !name.equals (GSParams.LANGUAGE)
    542           && !name.equals (GSXML.USER_ID_ATT)) {
    543 
    544           // lang and uid are stored but we dont want it in the param list cos its already in the request
    545           Element param = this.doc.createElement (GSXML.PARAM_ELEM);
    546           param.setAttribute (GSXML.NAME_ATT, name);
    547           String value =  GSXML.xmlSafe ((String)session.getAttribute (name));
    548 
    549           // ugly hack to undo : escaping
    550           value = StringUtils.replace(value, "%3A", "\\:");
    551           param.setAttribute (GSXML.VALUE_ATT,value);
    552           xml_param_list.appendChild (param);
    553         }
    554       }
    555     }
    556      
    557     if (!output.equals("html") && !output.equals("server") && !output.equals("xsltclient")) {
    558       response.setContentType ("text/xml"); // for now use text
    559     }
    560    
    561     //GSXML.printXMLNode(xml_message);
    562    
    563     Node xml_result = this.recept.process(xml_message);
    564     encodeURLs (xml_result, response);
    565     out.println (this.converter.getPrettyString (xml_result));
    566    
    567     displaySize(session_ids_table);
    568 
    569   } //end of doGet(HttpServletRequest, HttpServletResponse)
    570 
    571   //a debugging method
    572   private void displaySize(Hashtable table) {
    573     if(table == null) {
    574       logger.info("cached table is null");
    575       return;
    576     }
    577     if (table.size() == 0) {
    578       logger.info("cached table size is zero");
    579       return;
    580     }
    581     int num_cached_coll = 0;
    582     ArrayList cache_list = new ArrayList(table.values());
    583     for (int i=0; i<cache_list.size(); i++) {
    584       num_cached_coll += ((UserSessionCache)cache_list.get(i)).tableSize();
    585     }
    586     logger.info("Number of sessions : total number of cached collection info = " + table.size() + " : " + num_cached_coll);
    587   }
    588 
    589   /** merely a debugging method! */
    590   private String tableToString(Hashtable table) {
    591     String str = "";
    592     Enumeration keys = table.keys ();
    593     while(keys.hasMoreElements ()) {
    594       String name = (String)keys.nextElement();
    595       str += name + ", ";
    596     }
    597     return str;
    598   }
    599 
    600   /** this goes through each URL and adds in a session id if needed--
    601    * its needed if the browser doesn't accept cookies
    602    * also escapes things if needed
    603    */
    604   protected void encodeURLs(Node dataNode, HttpServletResponse response) {
    605    
    606     if (dataNode == null) {
    607       return;
    608     }
    609 
    610     Element data =null;
    611 
    612     short nodeType = dataNode.getNodeType();
    613     if (nodeType == Node.DOCUMENT_NODE) {
    614       Document docNode = (Document)dataNode;
    615       data = docNode.getDocumentElement() ;
    616     }
    617     else {
    618       data = (Element)dataNode;
    619     }
    620 
    621     if ( data != null ) {
    622 
    623         // get all the <a> elements
    624         NodeList hrefs = data.getElementsByTagName("a");
    625         // Instead of calculating each iteration...
    626         int hrefscount = hrefs.getLength();
    627 
    628         for (int i=0; hrefs!=null && i < hrefscount; i++) {
    629           Element a = (Element)hrefs.item(i);
    630           // ugly hack to get rid of : in the args - interferes with session handling
    631           String href = a.getAttribute("href");
    632           if (!href.equals("")) {
    633             if (href.indexOf("?")!=-1) {
    634               String[] parts = StringUtils.split(href, "\\?", -1);
    635               if (parts.length == 1)
    636               {
    637                 parts[0] = StringUtils.replace(parts[0], ":", "%3A");
    638                 href = "?"+parts[0];
    639               }
    640               else
    641               {
    642                 parts[1] = StringUtils.replace(parts[1], ":", "%3A");
    643                 href = parts[0]+"?"+parts[1];
    644               }
    645              
    646             }
    647             a.setAttribute("href", response.encodeURL(href));
    648           }
    649         }
    650        
    651         // now find any submit bits - get all the <form> elements
    652         NodeList forms = data.getElementsByTagName("form");
    653         int formscount = forms.getLength();
    654         for (int i=0; forms!=null && i < formscount; i++) {
    655           Element form = (Element)forms.item(i);
    656           form.setAttribute("action", response.encodeURL(form.getAttribute("action")));
    657         }
    658         // are these the only cases where URLs occur??
    659         // we should only do this for greenstone urls?
    660     }
    661    
    662   }
    663  
    664   synchronized protected int getNextUserId() {
    665     next_user_id++;
    666     return next_user_id;
    667   }
    668  
    669   public void doPost(HttpServletRequest request, HttpServletResponse response)
    670     throws ServletException, IOException {
    671 
    672     doGet(request,response);
    673    
    674   }
     40
     41    /** the receptionist to send messages to */
     42    protected Receptionist recept=null;
     43
     44    /** the default language - is specified by setting a servlet param,
     45* otherwise DEFAULT_LANG is used*/
     46    protected String default_lang= null;
     47
     48    /** Whether or not client-side XSLT support should be exposed */
     49    protected boolean supports_client_xslt = false;
     50
     51    /** The default default - used if a default lang is not specified
     52* in the servlet params */
     53    protected final String DEFAULT_LANG = "en";
     54
     55    /** container Document to create XML Nodes */
     56    protected Document doc=null;
     57
     58    /** a converter class to parse XML and create Docs */
     59    protected XMLConverter converter=null;
     60
     61    /** the cgi stuff - the Receptionist can add new args to this
     62*
     63* its used by the servlet to determine what args to save */
     64    protected GSParams params = null;
     65
     66    /** user id - new one per session. This doesn't work if session state is saved between restarts - this requires this value to be saved too. */
     67    protected int next_user_id = 0;
     68
     69    /** a hash that contains all the active session IDs mapped to the cached items
     70*  It is updated whenever the whole site or a particular collection is reconfigured
     71*  using the command a=s&sa=c or a=s&sa=c&c=xxx
     72*  It is in the form: sid -> (UserSessionCache object)
     73*/
     74    protected Hashtable session_ids_table = new Hashtable();
     75
     76    /** the maximum interval that the cached info remains in session_ids_table (in seconds)
     77*  This is set in web.xml
     78*/
     79    protected int session_expiration = 1800;
     80
     81    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.LibraryServlet.class.getName());
     82
     83    /** initialise the servlet
     84*/
     85    public void init(ServletConfig config) throws ServletException {
     86        // always call super.init;
     87        super.init(config);
     88        // disable preferences - does this work anyway??
     89        //System.setProperty("java.util.prefs.PreferencesFactory", "org.greenstone.gsdl3.util.DisabledPreferencesFactory");
     90       
     91        String library_name = config.getInitParameter(GSConstants.LIBRARY_NAME);
     92        String gsdl3_home = config.getInitParameter(GSConstants.GSDL3_HOME);
     93        String interface_name = config.getInitParameter(GSConstants.INTERFACE_NAME);
     94       
     95        String allowXslt = (String)config.getInitParameter(GSConstants.ALLOW_CLIENT_SIDE_XSLT);
     96        supports_client_xslt = allowXslt != null && allowXslt.equals("true");
     97       
     98        this.default_lang = config.getInitParameter(GSConstants.DEFAULT_LANG);
     99        String sess_expire = config.getInitParameter(GSXML.SESSION_EXPIRATION);
     100       
     101        if (sess_expire != null && !sess_expire.equals("")) {
     102            this.session_expiration = Integer.parseInt(sess_expire);
     103        }
     104       
     105        if (library_name == null || interface_name ==null) {
     106            // must have this
     107            System.err.println("initialisation parameters not all set!");
     108            System.err.println(" you must have libraryname and interfacename");
     109            System.exit(1);
     110        }
     111       
     112        String site_name = config.getInitParameter(GSConstants.SITE_NAME);
     113        String remote_site_name = null;
     114        String remote_site_type = null;
     115        String remote_site_address = null;
     116       
     117        if (site_name == null) {
     118            // no site, try for communicator
     119            remote_site_name = config.getInitParameter("remote_site_name");
     120            remote_site_type = config.getInitParameter("remote_site_type");
     121            remote_site_address = config.getInitParameter("remote_site_address");
     122            if (remote_site_name == null || remote_site_type == null || remote_site_address == null) {
     123                System.err.println("initialisation paramters not all set!");
     124                System.err.println("if site_name is not set, then you must have remote_site_name, remote_site_type and remote_site_address set");
     125                System.exit(1);
     126            }
     127        }
     128       
     129        if (this.default_lang == null) {
     130            // choose english
     131            this.default_lang = DEFAULT_LANG;
     132        }
     133       
     134        HashMap config_params = new HashMap();
     135       
     136        config_params.put(GSConstants.LIBRARY_NAME, library_name);
     137        config_params.put(GSConstants.INTERFACE_NAME, interface_name); 
     138        config_params.put(GSConstants.ALLOW_CLIENT_SIDE_XSLT, supports_client_xslt);
     139       
     140        if (site_name != null) {
     141            config_params.put(GSConstants.SITE_NAME, site_name);
     142        }
     143        this.converter = new XMLConverter();
     144        this.doc = this.converter.newDOM();
     145       
     146        // the receptionist -the servlet will talk to this
     147        String recept_name = (String)config.getInitParameter("receptionist_class");
     148        if (recept_name == null) {
     149            this.recept = new DefaultReceptionist();
     150        } else {
     151            try {
     152                this.recept = (Receptionist)Class.forName("org.greenstone.gsdl3.core."+recept_name).newInstance();
     153            } catch (Exception e) { // cant use this new one, so use normal one
     154                System.err.println("LibraryServlet configure exception when trying to use a new Receptionist "+recept_name+": "+e.getMessage());
     155                e.printStackTrace();
     156                this.recept = new DefaultReceptionist();
     157            }
     158        }
     159        this.recept.setConfigParams(config_params);
     160       
     161        // 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.
     162        if (site_name != null) {
     163            String mr_name = (String)config.getInitParameter("messagerouter_class");
     164            MessageRouter message_router = null;
     165            if (mr_name == null) { // just use the normal MR
     166                message_router = new MessageRouter();
     167            } else { // try the specified one
     168                try {
     169                    message_router = (MessageRouter)Class.forName("org.greenstone.gsdl3.core."+mr_name).newInstance();
     170                } catch (Exception e) { // cant use this new one, so use normal one
     171                    System.err.println("LibraryServlet configure exception when trying to use a new MessageRouter "+mr_name+": "+e.getMessage());
     172                    e.printStackTrace();
     173                    message_router = new MessageRouter();
     174                }
     175            }
     176           
     177            message_router.setSiteName(site_name);
     178            message_router.setLibraryName(library_name);
     179            message_router.configure();
     180            this.recept.setMessageRouter(message_router);
     181        } else {
     182            // talking to a remote site, create a communicator
     183            Communicator communicator = null;
     184            // we need to create the XML to configure the communicator
     185            Element site_elem = this.doc.createElement(GSXML.SITE_ELEM);
     186            site_elem.setAttribute(GSXML.TYPE_ATT, remote_site_type);
     187            site_elem.setAttribute(GSXML.NAME_ATT, remote_site_name);
     188            site_elem.setAttribute(GSXML.ADDRESS_ATT, remote_site_address);
     189           
     190            if (remote_site_type.equals(GSXML.COMM_TYPE_SOAP_JAVA)) {
     191                communicator = new SOAPCommunicator();
     192            } else {
     193                System.err.println("LibraryServlet.init Error: invalid Communicator type: "+remote_site_type);
     194                System.exit(1);
     195            }
     196           
     197            if (!communicator.configure(site_elem)) {
     198                System.err.println("LibraryServlet.init Error: Couldn't configure communicator");
     199                System.exit(1);
     200            }
     201            this.recept.setMessageRouter(communicator);
     202        }
     203       
     204        // the params arg thingy
     205       
     206        String params_name = (String)config.getInitParameter("params_class");
     207        if (params_name == null) {
     208            this.params = new GSParams();
     209        } else {
     210            try {
     211                this.params = (GSParams)Class.forName("org.greenstone.gsdl3.util."+params_name).newInstance();
     212            } catch (Exception e) {
     213                System.err.println("LibraryServlet configure exception when trying to use a new params thing "+params_name+": "+e.getMessage());
     214                e.printStackTrace();
     215                this.params = new GSParams();
     216            }
     217        }
     218        // pass it to the receptionist
     219        this.recept.setParams(this.params);
     220        this.recept.configure();
     221       
     222    }
     223
     224
     225    private void logUsageInfo(HttpServletRequest request){
     226        String usageInfo = "";
     227       
     228        //session-info: get params stored in the session
     229        HttpSession session = request.getSession(true);
     230        Enumeration attributeNames = session.getAttributeNames();
     231        while(attributeNames.hasMoreElements()) {
     232            String name = (String)attributeNames.nextElement();
     233            usageInfo +=name+"="+session.getAttribute(name)+" ";
     234        }
     235       
     236        //logged info = general-info + session-info
     237        usageInfo =
     238        request.getServletPath()+" "+ //serlvet
     239        "["+request.getQueryString()+"]" +" "+ //the query string
     240        "["+usageInfo.trim()+"]" +" "+ // params stored in a session
     241        request.getRemoteAddr()+" "+   //remote address
     242        request.getRequestedSessionId()+" "+ //session id
     243        request.getHeader("user-agent")+" "; //the remote brower info
     244       
     245        logger.info(usageInfo);
     246       
     247    }
     248
     249    public class UserSessionCache implements HttpSessionBindingListener {
     250
     251        String session_id = "";
     252       
     253        /** a hash that maps the session ID to a hashtable that maps the coll_name to its parameters
     254    *  coll_name -> Hashtable (param_name -> param_value)
     255    */
     256        protected Hashtable coll_name_params_table = null;
     257       
     258        public UserSessionCache(String id, Hashtable table) {
     259            session_id = id;     
     260            coll_name_params_table = (table == null)? new Hashtable() : table;     
     261        }
     262
     263        protected void cleanupCache(String coll_name) {
     264            if (coll_name_params_table.containsKey(coll_name)) {
     265                coll_name_params_table.remove(coll_name);
     266            }
     267        }
     268
     269        protected Hashtable getParamsTable() {
     270            return coll_name_params_table;
     271        }
     272
     273        public void valueBound(HttpSessionBindingEvent event) {
     274            // Do nothing
     275        }
     276
     277        public void valueUnbound(HttpSessionBindingEvent event) {
     278            if(session_ids_table.containsKey(session_id)) {
     279                session_ids_table.remove(session_id);
     280            }
     281        }
     282
     283        public int tableSize() {
     284            return (coll_name_params_table == null)? 0 : coll_name_params_table.size();
     285        }
     286
     287    }
     288
     289    public void doGet (HttpServletRequest request, HttpServletResponse response)
     290    throws ServletException, IOException {
     291        logUsageInfo (request);
     292
     293        String query_string = request.getQueryString();
     294        if (query_string!=null){
     295            String[] query_arr = StringUtils.split(query_string, "&");
     296            boolean redirect = false;
     297            String href = null;
     298            String rl = null;
     299            String[] nameval = new String[2]; // Reuse it for memory efficiency purposes   
     300
     301            for (int i=0;i<query_arr.length;i++){
     302
     303                if (query_arr[i].startsWith("el=")){
     304                    if (query_arr[i].substring(query_arr[i].indexOf("=")+1,query_arr[i].length()).equals("direct")){
     305                        redirect = true;
     306                    }
     307                }else if(query_arr[i].startsWith("href=")){
     308                    href = query_arr[i].substring(query_arr[i].indexOf("=")+1,query_arr[i].length());
     309                    href = StringUtils.replace(href, "%2f", "/");
     310                    href = StringUtils.replace(href, "%7e", "~");
     311                    href = StringUtils.replace(href, "%3f", "?");
     312                    href = StringUtils.replace(href, "%3A", "\\:");
     313                }else if(query_arr[i].startsWith("rl=")){
     314                    rl = query_arr[i].substring(query_arr[i].indexOf("=")+1,query_arr[i].length());
     315                }
     316            }
     317
     318            //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
     319            //"rl=0" this is an external link
     320            //"rl=1" this is an internal link
     321            if ((redirect) && (href != null) && (rl.equals("0"))){// This is an external link, the web page is re-directed to the external URL (&el=&rl=0&href="http://...")
     322                response.setContentType("text/xml");
     323                response.sendRedirect(href);
     324            }
     325        }
     326       
     327        // Nested Diagnostic Configurator to identify the client for
     328        HttpSession session = request.getSession (true);
     329        session.setMaxInactiveInterval(session_expiration);
     330        String uid = (String)session.getAttribute (GSXML.USER_ID_ATT);
     331        if (uid ==null) {
     332            uid = ""+getNextUserId ();
     333            session.setAttribute (GSXML.USER_ID_ATT, uid);
     334        }
     335        request.setCharacterEncoding ("UTF-8");
     336        response.setContentType ("text/html;charset=UTF-8");
     337        PrintWriter out = response.getWriter ();
     338       
     339        String lang = request.getParameter (GSParams.LANGUAGE);
     340        if (lang==null || lang.equals ("")) {
     341            // try the session cached lang
     342            lang = (String)session.getAttribute (GSParams.LANGUAGE);
     343            if (lang==null || lang.equals ("")) {
     344                // still not set, use the default
     345                lang = this.default_lang;
     346            }
     347        }
     348       
     349        // set the lang in the session
     350        session.setAttribute (GSParams.LANGUAGE, lang);
     351       
     352        String output = request.getParameter (GSParams.OUTPUT);
     353        if (output==null || output.equals ("")) {
     354            output = "html"; // uses html by default
     355        }
     356       
     357        // If server output, force a switch to traditional interface
     358        //output = (output.equals("server")) ? "html" : output;
     359       
     360        // Force change the output mode if client-side XSLT is supported - server vs. client
     361        // BUT only if the library allows client-side transforms   
     362        if(supports_client_xslt) {
     363            // MUST be done before the xml_message is built
     364            Cookie[] cookies = request.getCookies();
     365            Cookie xsltCookie = null;
     366           
     367            // The client has cookies enabled and a value set - use it!
     368            if(cookies != null) {
     369                for(Cookie c : cookies) {
     370                    if(c.getName().equals("supportsXSLT")) {
     371                        xsltCookie = c;
     372                        break;
     373                    }
     374                }
     375                output = (xsltCookie != null && xsltCookie.getValue().equals("true") && output.equals("html")) ? "xsltclient" : output;
     376            }
     377        }
     378       
     379        // the request to the receptionist
     380        Element xml_message = this.doc.createElement (GSXML.MESSAGE_ELEM);
     381        Element xml_request = GSXML.createBasicRequest (this.doc, GSXML.REQUEST_TYPE_PAGE, "", lang, uid);
     382        xml_request.setAttribute (GSXML.OUTPUT_ATT, output);
     383       
     384        xml_message.appendChild (xml_request);
     385       
     386        String action = request.getParameter (GSParams.ACTION);
     387        String subaction = request.getParameter (GSParams.SUBACTION);
     388        String collection = request.getParameter(GSParams.COLLECTION);
     389        String service = request.getParameter(GSParams.SERVICE);
     390
     391        // We clean up the cache session_ids_table if system
     392        // commands are issued (and also don't need to do caching for this request)
     393        boolean should_cache = true;
     394        if(action != null && action.equals(GSParams.SYSTEM)) {
     395            should_cache = false;
     396
     397            // we may want to remove all collection cache info, or just a specific collection
     398            boolean clean_all = true;
     399            String clean_collection = null;
     400            // system commands are to activate/deactivate stuff
     401            // collection param is in the sc parameter.
     402            // don't like the fact that it is hard coded here
     403            String coll = request.getParameter(GSParams.SYSTEM_CLUSTER);
     404            if (coll != null && !coll.equals("")) {
     405                clean_all = false;
     406                clean_collection = coll;
     407            } else {
     408                // check other system types
     409                if (subaction.equals("a") || subaction.equals("d")) {
     410                    String module_name = request.getParameter("sn");
     411                    if (module_name != null && !module_name.equals("")) {
     412                        clean_all = false;
     413                        clean_collection = module_name;
     414                    }
     415                }
     416            }
     417            if (clean_all) {
     418                session_ids_table = new Hashtable();
     419                session.removeAttribute(GSXML.USER_SESSION_CACHE_ATT);
     420            } else {
     421                // just clean up info for clean_collection
     422                ArrayList cache_list = new ArrayList(session_ids_table.values());
     423                for (int i=0; i<cache_list.size(); i++) {
     424                    UserSessionCache cache = (UserSessionCache)cache_list.get(i);
     425                    cache.cleanupCache(clean_collection);
     426                }
     427               
     428            }
     429
     430        }
     431       
     432        // cache_key is the collection name, or service name
     433        String cache_key = collection;
     434        if (cache_key == null || cache_key.equals("")) {
     435            cache_key = service;
     436        }
     437       
     438        // logger.info("should_cache= " + should_cache);
     439
     440        //clear the collection-specific cache in the session, since we have no way to know whether this session is
     441        //about the same collection as the last session or not.
     442        Enumeration attributeNames = session.getAttributeNames();
     443        while(attributeNames.hasMoreElements()) {
     444            String name = (String)attributeNames.nextElement();
     445            if (!name.equals (GSXML.USER_SESSION_CACHE_ATT)
     446                    && !name.equals (GSParams.LANGUAGE)
     447                    && !name.equals (GSXML.USER_ID_ATT)) {
     448
     449                session.removeAttribute(name);
     450            }
     451        }
     452       
     453        UserSessionCache session_cache = null;
     454        Hashtable param_table = null;   
     455        Hashtable table = null;
     456        String sid = session.getId();
     457        if (should_cache == true && cache_key != null && !cache_key.equals("")) {
     458            if (session_ids_table.containsKey(sid)) {
     459                session_cache = (UserSessionCache)session_ids_table.get(sid);
     460                param_table = session_cache.getParamsTable();
     461                logger.info("collections in table: " + tableToString(param_table));
     462                if (param_table.containsKey(cache_key)) {
     463                    //logger.info("existing table: " + collection);
     464                    table = (Hashtable)param_table.get(cache_key);
     465                } else {
     466                    table = new Hashtable();
     467                    param_table.put(cache_key, table);
     468                    //logger.info("new table: " + collection);
     469                }
     470            } else {
     471                param_table = new Hashtable();
     472                table = new Hashtable();
     473                param_table.put(cache_key, table);
     474                session_cache = new UserSessionCache(sid, param_table);
     475                session_ids_table.put(sid, session_cache);
     476                session.setAttribute(GSXML.USER_SESSION_CACHE_ATT, session_cache);
     477                //logger.info("new session id");
     478            }
     479        }
     480
     481        if (action==null || action.equals ("")) {
     482            // should we do all the following stuff if using default page?
     483            // display the home page  - the default page
     484            xml_request.setAttribute (GSXML.ACTION_ATT, "p");
     485            xml_request.setAttribute (GSXML.SUBACTION_ATT, PageAction.HOME_PAGE);
     486        }
     487        else {
     488            xml_request.setAttribute (GSXML.ACTION_ATT, action);
     489            if (subaction != null) {
     490                xml_request.setAttribute (GSXML.SUBACTION_ATT, subaction);
     491            }
     492           
     493            //  create the param list for the greenstone request - includes
     494            // the params from the current request and any others from the saved session
     495            Element xml_param_list = this.doc.createElement (GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
     496            xml_request.appendChild (xml_param_list);
     497           
     498            Enumeration params = request.getParameterNames ();
     499            while(params.hasMoreElements ()) {
     500                String name = (String)params.nextElement ();
     501                if (!name.equals (GSParams.ACTION)
     502                        && !name.equals (GSParams.SUBACTION)
     503                        && !name.equals (GSParams.LANGUAGE)
     504                        && !name.equals (GSParams.OUTPUT)) {// we have already dealt with these
     505                   
     506                    String value="";
     507                    String [] values = request.getParameterValues (name);
     508                    value = values[0];
     509                    if (values.length > 1) {
     510                        for (int i=1; i< values.length; i++) {
     511                            value += ","+values[i];
     512                        }
     513                    }
     514                    // either add it to the param list straight away, or save it to the session and add it later
     515                    if (this.params.shouldSave (name) && table != null) {
     516                        table.put(name, value);
     517                    } else {
     518                        Element param = this.doc.createElement (GSXML.PARAM_ELEM);
     519                        param.setAttribute (GSXML.NAME_ATT, name);
     520                        param.setAttribute (GSXML.VALUE_ATT, GSXML.xmlSafe (value));
     521                        xml_param_list.appendChild (param);
     522                    }
     523                }
     524            }
     525            //put everything in the table into the session
     526            // do we need to do this? why not just put from table into param list
     527            if (table != null) {
     528                Enumeration keys = table.keys ();
     529                while(keys.hasMoreElements ()) {
     530                    String name = (String)keys.nextElement();
     531                    session.setAttribute(name, (String)table.get(name));
     532                }
     533            }
     534           
     535            // put in all the params from the session cache
     536            params = session.getAttributeNames ();
     537            while(params.hasMoreElements ()) {
     538                String name = (String)params.nextElement ();
     539               
     540                if ( !name.equals (GSXML.USER_SESSION_CACHE_ATT)
     541                        && !name.equals (GSParams.LANGUAGE)
     542                        && !name.equals (GSXML.USER_ID_ATT)) {
     543
     544                    // lang and uid are stored but we dont want it in the param list cos its already in the request
     545                    Element param = this.doc.createElement (GSXML.PARAM_ELEM);
     546                    param.setAttribute (GSXML.NAME_ATT, name);
     547                    String value =  GSXML.xmlSafe ((String)session.getAttribute (name));
     548
     549                    // ugly hack to undo : escaping
     550                    value = StringUtils.replace(value, "%3A", "\\:");
     551                    param.setAttribute (GSXML.VALUE_ATT,value);
     552                    xml_param_list.appendChild (param);
     553                }
     554            }
     555        }
     556       
     557        if (!output.equals("html") && !output.equals("server") && !output.equals("xsltclient")) {
     558            response.setContentType ("text/xml"); // for now use text
     559        }
     560       
     561        //Add custom HTTP headers if requested
     562        String httpHeaders = StringEscapeUtils.unescapeHtml4(request.getParameter(GSParams.HTTPHEADERFIELDS));
     563        if (httpHeaders!=null && !httpHeaders.equals ("")) {
     564            String[] headerParams = StringUtils.split(httpHeaders, "&");
     565           
     566            for(int j = 0; j < headerParams.length; j++)
     567            {
     568                int index = StringUtils.indexOf(headerParams[j], "=");
     569               
     570                if(index != -1)
     571                {
     572                    response.setHeader(StringUtils.substring(headerParams[j], 0, index), StringUtils.substring(headerParams[j], index+1));
     573                }
     574            }
     575           
     576        }
     577       
     578        //GSXML.printXMLNode(xml_message);
     579        Node xml_result = this.recept.process(xml_message);
     580        encodeURLs (xml_result, response);
     581        out.println (this.converter.getPrettyString (xml_result));
     582       
     583        displaySize(session_ids_table);
     584
     585    } //end of doGet(HttpServletRequest, HttpServletResponse)
     586
     587    //a debugging method
     588    private void displaySize(Hashtable table) {
     589        if(table == null) {
     590            logger.info("cached table is null");
     591            return;
     592        }
     593        if (table.size() == 0) {
     594            logger.info("cached table size is zero");
     595            return;
     596        }
     597        int num_cached_coll = 0;
     598        ArrayList cache_list = new ArrayList(table.values());
     599        for (int i=0; i<cache_list.size(); i++) {
     600            num_cached_coll += ((UserSessionCache)cache_list.get(i)).tableSize();
     601        }
     602        logger.info("Number of sessions : total number of cached collection info = " + table.size() + " : " + num_cached_coll);
     603    }
     604
     605    /** merely a debugging method! */
     606    private String tableToString(Hashtable table) {
     607        String str = "";
     608        Enumeration keys = table.keys ();
     609        while(keys.hasMoreElements ()) {
     610            String name = (String)keys.nextElement();
     611            str += name + ", ";
     612        }
     613        return str;
     614    }
     615
     616    /** this goes through each URL and adds in a session id if needed--
     617* its needed if the browser doesn't accept cookies
     618* also escapes things if needed
     619*/
     620    protected void encodeURLs(Node dataNode, HttpServletResponse response) {
     621       
     622        if (dataNode == null) {
     623            return;
     624        }
     625
     626        Element data =null;
     627
     628        short nodeType = dataNode.getNodeType();
     629        if (nodeType == Node.DOCUMENT_NODE) {
     630            Document docNode = (Document)dataNode;
     631            data = docNode.getDocumentElement() ;
     632        }
     633        else {
     634            data = (Element)dataNode;
     635        }
     636
     637        if ( data != null ) {
     638
     639            // get all the <a> elements
     640            NodeList hrefs = data.getElementsByTagName("a");
     641            // Instead of calculating each iteration...
     642            int hrefscount = hrefs.getLength();
     643
     644            for (int i=0; hrefs!=null && i < hrefscount; i++) {
     645                Element a = (Element)hrefs.item(i);
     646                // ugly hack to get rid of : in the args - interferes with session handling
     647                String href = a.getAttribute("href");
     648                if (!href.equals("")) {
     649                    if (href.indexOf("?")!=-1) {
     650                        String[] parts = StringUtils.split(href, "\\?", -1);
     651                        if (parts.length == 1)
     652                        {
     653                            parts[0] = StringUtils.replace(parts[0], ":", "%3A");
     654                            href = "?"+parts[0];
     655                        }
     656                        else
     657                        {
     658                            parts[1] = StringUtils.replace(parts[1], ":", "%3A");
     659                            href = parts[0]+"?"+parts[1];
     660                        }
     661                       
     662                    }
     663                    a.setAttribute("href", response.encodeURL(href));
     664                }
     665            }
     666           
     667            // now find any submit bits - get all the <form> elements
     668            NodeList forms = data.getElementsByTagName("form");
     669            int formscount = forms.getLength();
     670            for (int i=0; forms!=null && i < formscount; i++) {
     671                Element form = (Element)forms.item(i);
     672                form.setAttribute("action", response.encodeURL(form.getAttribute("action")));
     673            }
     674            // are these the only cases where URLs occur??
     675            // we should only do this for greenstone urls?
     676        }
     677       
     678    }
     679
     680    synchronized protected int getNextUserId() {
     681        next_user_id++;
     682        return next_user_id;
     683    }
     684
     685    public void doPost(HttpServletRequest request, HttpServletResponse response)
     686    throws ServletException, IOException {
     687
     688        doGet(request,response);
     689       
     690    }
    675691
    676692}
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSParams.java

    r23968 r24019  
    2929    public static final String RESPONSE_ONLY = "ro"; // if == 1 do the request and pass back the response xml - no page formatting
    3030    public static final String OUTPUT = "o"; // if processing is to be done, what type of output - html/xml/other??
     31    public static final String HTTPHEADERFIELDS = "hhf";
    3132    public static final String SERVICE = "s"; // the name of the service
    3233    public static final String CLUSTER = "c";   // these two are the same
Note: See TracChangeset for help on using the changeset viewer.