Changeset 14498

Show
Ignore:
Timestamp:
06.09.2007 18:08:23 (12 years ago)
Author:
xiao
Message:

modify to make the session caching collection-specific.

Files:
1 modified

Legend:

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

    r13273 r14498  
    1212import javax.servlet.http.*; 
    1313import java.util.Enumeration; 
     14import java.util.ArrayList; 
    1415import java.util.HashMap; 
    1516import java.io.File; 
    16  
     17import java.util.Hashtable; 
    1718import org.apache.log4j.*; 
     19 
    1820 
    1921/** a servlet to serve the greenstone library - we are using servlets instead 
     
    2224 * are loaded. Each time a request comes in to the servlet, the session() 
    2325 * method is called in a new thread (calls doGet/doPut etc) 
    24  * takes the a=p&p=home type args and builds a simple request to send to  
     26 * takes the a=p&p=home type args and builds a simple request to send to 
    2527 * its receptionist, which returns a result in html, cos output=html 
    2628 * is set in the request 
     29 *  
     30 * 18/Jul/07 xiao 
     31 * modify to make the cached parameters collection-specific. 
     32 * Most of the work is done in doGet(), except adding an inner class UserSessionCache. 
     33 *  
    2734 * @see Receptionist 
    2835 */ 
    2936public class LibraryServlet extends HttpServlet { 
    30      
    31     /** the receptionist to send messages to */ 
    32     protected Receptionist recept=null; 
    33     /** the default language - is specified by setting a servlet param, 
    34      * otherwise DEFAULT_LANG is used*/ 
    35     protected String default_lang= null; 
    36     /** The default default - used if a default lang is not specified  
    37      * in the servlet params */ 
    38     protected final String DEFAULT_LANG = "en"; 
    39     /** container Document to create XML Nodes */ 
    40     protected Document doc=null;     
    41     /** a converter class to parse XML and create Docs */ 
    42     protected XMLConverter converter=null; 
    43     /** the cgi stuff - the Receptionist can add new args to this 
    44      * its used by the servlet to determine what args to save */ 
    45     protected GSParams params = null; 
    46  
    47     /** 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. */ 
    48     protected int next_user_id = 0; 
    49  
    50     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.LibraryServlet.class.getName()); 
    51  
    52     /** initialise the servlet 
     37   
     38  /** the receptionist to send messages to */ 
     39  protected Receptionist recept=null; 
     40  /** the default language - is specified by setting a servlet param, 
     41   * otherwise DEFAULT_LANG is used*/ 
     42  protected String default_lang= null; 
     43  /** The default default - used if a default lang is not specified 
     44   * in the servlet params */ 
     45  protected final String DEFAULT_LANG = "en"; 
     46  /** container Document to create XML Nodes */ 
     47  protected Document doc=null; 
     48  /** a converter class to parse XML and create Docs */ 
     49  protected XMLConverter converter=null; 
     50  /** the cgi stuff - the Receptionist can add new args to this 
     51   * 
     52   * its used by the servlet to determine what args to save */ 
     53  protected GSParams params = null; 
     54   
     55  /** 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. */ 
     56  protected int next_user_id = 0; 
     57 
     58  /** a hash that contains all the active session IDs mapped to the cached items 
     59   *  It is updated whenever the whole site or a particular collection is reconfigured 
     60   *  using the command a=s&sa=c or a=s&sa=c&c=xxx 
     61   *  It is in the form: sid -> (UserSessionCache object) 
     62   */ 
     63  protected Hashtable session_ids_table = new Hashtable(); 
     64  //this name is combined with the collection name and used for caching  
     65  protected String valid_site_name = ""; 
     66   
     67  /** the maximum interval that the cached info remains in session_ids_table (in seconds)  
     68   *  This is set in web.xml 
     69   */ 
     70  protected int session_expiration = 1800; 
     71   
     72  static Logger logger = Logger.getLogger(org.greenstone.gsdl3.LibraryServlet.class.getName()); 
     73   
     74  /** initialise the servlet 
     75   */ 
     76  public void init(ServletConfig config) throws ServletException { 
     77    // always call super.init; 
     78    super.init(config); 
     79    // disable preferences - does this work anyway?? 
     80    //System.setProperty("java.util.prefs.PreferencesFactory", "org.greenstone.gsdl3.util.DisabledPreferencesFactory"); 
     81     
     82     
     83    String library_name = config.getInitParameter(GSConstants.LIBRARY_NAME); 
     84    String gsdl3_home = config.getInitParameter(GSConstants.GSDL3_HOME); 
     85    String interface_name = config.getInitParameter(GSConstants.INTERFACE_NAME); 
     86    this.default_lang = config.getInitParameter(GSConstants.DEFAULT_LANG); 
     87    String sess_expire = config.getInitParameter(GSXML.SESSION_EXPIRATION); 
     88    if (sess_expire != null && !sess_expire.equals("")) { 
     89        this.session_expiration = Integer.parseInt(sess_expire); 
     90    } 
     91     
     92    if (library_name == null || interface_name ==null) { 
     93      // must have this 
     94      System.err.println("initialisation parameters not all set!"); 
     95      System.err.println(" you must have libraryname and interfacename"); 
     96      System.exit(1); 
     97    } 
     98     
     99    String site_name = config.getInitParameter(GSConstants.SITE_NAME); 
     100    String remote_site_name = null; 
     101    String remote_site_type = null; 
     102    String remote_site_address = null; 
     103     
     104    if (site_name == null) { 
     105      // no site, try for communicator 
     106      remote_site_name = config.getInitParameter("remote_site_name"); 
     107      remote_site_type = config.getInitParameter("remote_site_type"); 
     108      remote_site_address = config.getInitParameter("remote_site_address"); 
     109      if (remote_site_name == null || remote_site_type == null || remote_site_address == null) { 
     110        System.err.println("initialisation paramters not all set!"); 
     111        System.err.println("if site_name is not set, then you must have remote_site_name, remote_site_type and remote_site_address set"); 
     112        System.exit(1); 
     113      } 
     114    } 
     115    valid_site_name = (site_name != null)? site_name : remote_site_name; 
     116     
     117    if (this.default_lang == null) { 
     118      // choose english 
     119      this.default_lang = DEFAULT_LANG; 
     120    } 
     121     
     122    HashMap config_params = new HashMap(); 
     123     
     124    config_params.put(GSConstants.LIBRARY_NAME, library_name); 
     125    config_params.put(GSConstants.INTERFACE_NAME, interface_name); 
     126    if (site_name != null) { 
     127      config_params.put(GSConstants.SITE_NAME, site_name); 
     128    } 
     129    this.converter = new XMLConverter(); 
     130    this.doc = this.converter.newDOM(); 
     131     
     132    // the receptionist -the servlet will talk to this 
     133    String recept_name = (String)config.getInitParameter("receptionist_class"); 
     134    if (recept_name == null) { 
     135      this.recept = new DefaultReceptionist(); 
     136    } else { 
     137      try { 
     138        this.recept = (Receptionist)Class.forName("org.greenstone.gsdl3.core."+recept_name).newInstance(); 
     139      } catch (Exception e) { // cant use this new one, so use normal one 
     140        System.err.println("LibraryServlet configure exception when trying to use a new Receptionist "+recept_name+": "+e.getMessage()); 
     141        e.printStackTrace(); 
     142        this.recept = new DefaultReceptionist(); 
     143      } 
     144    } 
     145    this.recept.setConfigParams(config_params); 
     146     
     147    // 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. 
     148    if (site_name != null) { 
     149      String mr_name = (String)config.getInitParameter("messagerouter_class"); 
     150      MessageRouter message_router = null; 
     151      if (mr_name == null) { // just use the normal MR 
     152        message_router = new MessageRouter(); 
     153      } else { // try the specified one 
     154        try { 
     155          message_router = (MessageRouter)Class.forName("org.greenstone.gsdl3.core."+mr_name).newInstance(); 
     156        } catch (Exception e) { // cant use this new one, so use normal one 
     157          System.err.println("LibraryServlet configure exception when trying to use a new MessageRouter "+mr_name+": "+e.getMessage()); 
     158          e.printStackTrace(); 
     159          message_router = new MessageRouter(); 
     160        } 
     161      } 
     162       
     163      message_router.setSiteName(site_name); 
     164      message_router.configure(); 
     165      this.recept.setMessageRouter(message_router); 
     166    } else { 
     167      // talking to a remote site, create a communicator 
     168      Communicator communicator = null; 
     169      // we need to create the XML to configure the communicator 
     170      Element site_elem = this.doc.createElement(GSXML.SITE_ELEM); 
     171      site_elem.setAttribute(GSXML.TYPE_ATT, remote_site_type); 
     172      site_elem.setAttribute(GSXML.NAME_ATT, remote_site_name); 
     173      site_elem.setAttribute(GSXML.ADDRESS_ATT, remote_site_address); 
     174       
     175      if (remote_site_type.equals(GSXML.COMM_TYPE_SOAP_JAVA)) { 
     176        communicator = new SOAPCommunicator(); 
     177      } else { 
     178        System.err.println("LibraryServlet.init Error: invalid Communicator type: "+remote_site_type); 
     179        System.exit(1); 
     180      } 
     181       
     182      if (!communicator.configure(site_elem)) { 
     183        System.err.println("LibraryServlet.init Error: Couldn't configure communicator"); 
     184        System.exit(1); 
     185      } 
     186      this.recept.setMessageRouter(communicator); 
     187    } 
     188     
     189    // the params arg thingy 
     190     
     191    String params_name = (String)config.getInitParameter("params_class"); 
     192    if (params_name == null) { 
     193      this.params = new GSParams(); 
     194    } else { 
     195      try { 
     196        this.params = (GSParams)Class.forName("org.greenstone.gsdl3.util."+params_name).newInstance(); 
     197      } catch (Exception e) { 
     198        System.err.println("LibraryServlet configure exception when trying to use a new params thing "+params_name+": "+e.getMessage()); 
     199        e.printStackTrace(); 
     200        this.params = new GSParams(); 
     201      } 
     202    } 
     203    // pass it to the receptionist 
     204    this.recept.setParams(this.params); 
     205    this.recept.configure(); 
     206     
     207  } 
     208   
     209   
     210  private void logUsageInfo(HttpServletRequest request){ 
     211    String usageInfo = ""; 
     212     
     213    //session-info: get params stored in the session 
     214    HttpSession session = request.getSession(true); 
     215    Enumeration attributeNames = session.getAttributeNames(); 
     216    while(attributeNames.hasMoreElements()) { 
     217      String name = (String)attributeNames.nextElement(); 
     218      usageInfo +=name+"="+session.getAttribute(name)+" "; 
     219    } 
     220     
     221    //logged info = general-info + session-info 
     222    usageInfo = 
     223      request.getServletPath()+" "+ //serlvet 
     224      "["+request.getQueryString()+"]" +" "+ //the query string 
     225      "["+usageInfo.trim()+"]" +" "+ // params stored in a session 
     226      request.getRemoteAddr()+" "+   //remote address 
     227      request.getRequestedSessionId()+" "+ //session id 
     228      request.getHeader("user-agent")+" "; //the remote brower info 
     229     
     230    logger.info(usageInfo); 
     231     
     232  } 
     233   
     234  public class UserSessionCache implements HttpSessionBindingListener { 
     235 
     236    String session_id = ""; 
     237     
     238    /** a hash that maps the session ID to a hashtable that maps the coll_name to its parameters  
     239     *  coll_name -> Hashtable (param_name -> param_value) 
    53240     */ 
    54     public void init(ServletConfig config) throws ServletException { 
    55     // always call super.init; 
    56     super.init(config); 
    57     // disable preferences - does this work anyway?? 
    58     //System.setProperty("java.util.prefs.PreferencesFactory", "org.greenstone.gsdl3.util.DisabledPreferencesFactory"); 
    59  
    60      
    61     String library_name = config.getInitParameter(GSConstants.LIBRARY_NAME); 
    62     String gsdl3_home = config.getInitParameter(GSConstants.GSDL3_HOME); 
    63     String interface_name = config.getInitParameter(GSConstants.INTERFACE_NAME); 
    64     this.default_lang = config.getInitParameter(GSConstants.DEFAULT_LANG); 
    65  
    66     if (library_name == null || interface_name ==null) { 
    67         // must have this 
    68         System.err.println("initialisation parameters not all set!"); 
    69         System.err.println(" you must have libraryname and interfacename"); 
    70         System.exit(1); 
     241    protected Hashtable coll_name_params_table = null; 
     242     
     243    public UserSessionCache(String id, Hashtable table) { 
     244      session_id = id;       
     245      coll_name_params_table = (table == null)? new Hashtable() : table;       
     246    } 
     247 
     248    protected void cleanupCache(String coll_name) { 
     249      if (coll_name_params_table.containsKey(coll_name)) { 
     250          coll_name_params_table.remove(coll_name); 
     251      } 
     252    } 
     253    protected Hashtable getParamsTable() { 
     254        return coll_name_params_table; 
     255    } 
     256    public void valueBound(HttpSessionBindingEvent event) { 
     257    // Do nothing 
     258    } 
     259 
     260    public void valueUnbound(HttpSessionBindingEvent event) { 
     261      if(session_ids_table.containsKey(session_id)) { 
     262        session_ids_table.remove(session_id); 
     263      } 
     264    } 
     265    public int tableSize() { 
     266        return (coll_name_params_table == null)? 0 : coll_name_params_table.size(); 
     267    } 
     268  } 
     269   
     270  public void doGet (HttpServletRequest request, 
     271    HttpServletResponse response) 
     272    throws ServletException, IOException { 
     273    logUsageInfo (request); 
     274    //logger.info("---------------------------------------------------"); 
     275    // Nested Diagnostic Configurator to identify the client for 
     276     
     277    HttpSession session = request.getSession (true); 
     278    String uid = (String)session.getAttribute (GSXML.USER_ID_ATT); 
     279    if (uid ==null) { 
     280      uid = ""+getNextUserId (); 
     281      session.setAttribute (GSXML.USER_ID_ATT, uid); 
     282    } 
     283    request.setCharacterEncoding ("UTF-8"); 
     284    response.setContentType ("text/html;charset=UTF-8"); 
     285    PrintWriter out = response.getWriter (); 
     286     
     287    String lang = request.getParameter (GSParams.LANGUAGE); 
     288    if (lang==null || lang.equals ("")) { 
     289      // try the session cached lang 
     290      lang = (String)session.getAttribute (GSParams.LANGUAGE); 
     291      if (lang==null || lang.equals ("")) { 
     292        // still not set, use the default 
     293        lang = this.default_lang; 
     294      } 
     295    } 
     296     
     297    // set the lang in the session 
     298    session.setAttribute (GSParams.LANGUAGE, lang); 
     299     
     300    String output = request.getParameter (GSParams.OUTPUT); 
     301    if (output==null || output.equals ("")) { 
     302      output = "html"; // uses html by default 
     303    } 
     304     
     305    // the request to the receptionist 
     306    Element xml_message = this.doc.createElement (GSXML.MESSAGE_ELEM); 
     307    Element xml_request = GSXML.createBasicRequest (this.doc, GSXML.REQUEST_TYPE_PAGE, "", lang, uid); 
     308    xml_request.setAttribute (GSXML.OUTPUT_ATT, output); 
     309    xml_message.appendChild (xml_request); 
     310     
     311    String action = request.getParameter (GSParams.ACTION); 
     312    String subaction = request.getParameter (GSParams.SUBACTION); 
     313    String collection = request.getParameter(GSParams.COLLECTION); 
     314 
     315    //specifically we clean up the cache session_ids_table if the two reconfigure command 
     316    //are issued: a=s&sa=c and a=s&sa=c&c=coll_name, in which case there is no caching action to be taken 
     317    boolean should_cache = true; 
     318    if(action != null && action.equals(GSParams.SYSTEM)  
     319            && subaction != null && subaction.equals(GSParams.CONFIGURE)) { 
     320        if (collection == null || collection.equals("")) { 
     321            //user reconfiugred the whole site, clean up all cached info 
     322            //logger.info("clear cache for the whole site."); 
     323            session_ids_table = new Hashtable();  
     324             
     325        } else { 
     326            //clean up all cache info related to the collection 
     327            //logger.info("clear cache for collection: " + collection); 
     328            ArrayList cache_list = new ArrayList(session_ids_table.values()); 
     329            for (int i=0; i<cache_list.size(); i++) { 
     330                UserSessionCache cache = (UserSessionCache)cache_list.get(i); 
     331                cache.cleanupCache(collection); 
     332            } 
     333        } 
     334        should_cache = false; 
    71335    } 
    72336 
    73     String site_name = config.getInitParameter(GSConstants.SITE_NAME); 
    74     String remote_site_name = null; 
    75     String remote_site_type = null; 
    76     String remote_site_address = null; 
    77      
    78     if (site_name == null) { 
    79         // no site, try for communicator 
    80         remote_site_name = config.getInitParameter("remote_site_name"); 
    81         remote_site_type = config.getInitParameter("remote_site_type"); 
    82         remote_site_address = config.getInitParameter("remote_site_address"); 
    83         if (remote_site_name == null || remote_site_type == null || remote_site_address == null) { 
    84         System.err.println("initialisation paramters not all set!"); 
    85         System.err.println("if site_name is not set, then you must have remote_site_name, remote_site_type and remote_site_address set"); 
    86         System.exit(1);  
    87         } 
    88     } 
    89      
    90     if (this.default_lang == null) { 
    91         // choose english 
    92         this.default_lang = DEFAULT_LANG; 
    93     } 
    94      
    95     HashMap config_params = new HashMap(); 
    96      
    97     config_params.put(GSConstants.LIBRARY_NAME, library_name); 
    98     config_params.put(GSConstants.INTERFACE_NAME, interface_name); 
    99     if (site_name != null) { 
    100         config_params.put(GSConstants.SITE_NAME, site_name); 
    101     } 
    102     this.converter = new XMLConverter(); 
    103     this.doc = this.converter.newDOM(); 
    104      
    105     // the receptionist -the servlet will talk to this 
    106     String recept_name = (String)config.getInitParameter("receptionist_class"); 
    107     if (recept_name == null) { 
    108         this.recept = new DefaultReceptionist(); 
    109     } else { 
    110         try { 
    111         this.recept = (Receptionist)Class.forName("org.greenstone.gsdl3.core."+recept_name).newInstance(); 
    112         } catch (Exception e) { // cant use this new one, so use normal one 
    113         System.err.println("LibraryServlet configure exception when trying to use a new Receptionist "+recept_name+": "+e.getMessage()); 
    114         e.printStackTrace(); 
    115         this.recept = new DefaultReceptionist(); 
    116         } 
    117     } 
    118     this.recept.setConfigParams(config_params); 
    119  
    120     // 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. 
    121     if (site_name != null) { 
    122         String mr_name = (String)config.getInitParameter("messagerouter_class"); 
    123         MessageRouter message_router = null; 
    124         if (mr_name == null) { // just use the normal MR 
    125         message_router = new MessageRouter(); 
    126         } else { // try the specified one 
    127         try { 
    128             message_router = (MessageRouter)Class.forName("org.greenstone.gsdl3.core."+mr_name).newInstance(); 
    129         } catch (Exception e) { // cant use this new one, so use normal one 
    130             System.err.println("LibraryServlet configure exception when trying to use a new MessageRouter "+mr_name+": "+e.getMessage()); 
    131             e.printStackTrace(); 
    132             message_router = new MessageRouter(); 
    133         }    
    134         } 
    135          
    136         message_router.setSiteName(site_name); 
    137         message_router.configure(); 
    138         this.recept.setMessageRouter(message_router); 
    139     } else { 
    140         // talking to a remote site, create a communicator 
    141         Communicator communicator = null; 
    142         // we need to create the XML to configure the communicator 
    143         Element site_elem = this.doc.createElement(GSXML.SITE_ELEM); 
    144         site_elem.setAttribute(GSXML.TYPE_ATT, remote_site_type); 
    145         site_elem.setAttribute(GSXML.NAME_ATT, remote_site_name); 
    146         site_elem.setAttribute(GSXML.ADDRESS_ATT, remote_site_address); 
    147  
    148         if (remote_site_type.equals(GSXML.COMM_TYPE_SOAP_JAVA)) { 
    149         communicator = new SOAPCommunicator(); 
    150         } else { 
    151         System.err.println("LibraryServlet.init Error: invalid Communicator type: "+remote_site_type); 
    152         System.exit(1); 
    153         } 
    154          
    155         if (!communicator.configure(site_elem)) { 
    156         System.err.println("LibraryServlet.init Error: Couldn't configure communicator"); 
    157         System.exit(1); 
    158         } 
    159         this.recept.setMessageRouter(communicator); 
    160     } 
    161      
    162     // the params arg thingy 
    163      
    164     String params_name = (String)config.getInitParameter("params_class"); 
    165     if (params_name == null) { 
    166         this.params = new GSParams(); 
    167     } else { 
    168         try { 
    169         this.params = (GSParams)Class.forName("org.greenstone.gsdl3.util."+params_name).newInstance(); 
    170         } catch (Exception e) { 
    171         System.err.println("LibraryServlet configure exception when trying to use a new params thing "+params_name+": "+e.getMessage()); 
    172         e.printStackTrace(); 
    173         this.params = new GSParams(); 
    174         } 
    175     } 
    176     // pass it to the receptionist 
    177     this.recept.setParams(this.params); 
    178     this.recept.configure(); 
    179      
    180     } 
    181  
    182  
    183     private void logUsageInfo(HttpServletRequest request){ 
    184     String usageInfo = ""; 
    185  
    186     //session-info: get params stored in the session 
    187     HttpSession session = request.getSession(true); 
    188         Enumeration attributeNames = session.getAttributeNames(); 
    189     while(attributeNames.hasMoreElements()) { 
    190         String name = (String)attributeNames.nextElement(); 
    191         usageInfo +=name+"="+session.getAttribute(name)+" "; 
    192     } 
    193      
    194     //logged info = general-info + session-info 
    195     usageInfo =  
    196         request.getServletPath()+" "+ //serlvet 
    197         "["+request.getQueryString()+"]" +" "+ //the query string 
    198         "["+usageInfo.trim()+"]" +" "+ // params stored in a session 
    199         request.getRemoteAddr()+" "+   //remote address                   
    200         request.getRequestedSessionId()+" "+ //session id 
    201         request.getHeader("user-agent")+" "; //the remote brower info                       
    202                           
    203     logger.info(usageInfo); 
    204  
    205     } 
    206  
    207         
    208     public void doGet(HttpServletRequest request, 
    209               HttpServletResponse response) 
    210     throws ServletException, IOException { 
    211  
    212     logUsageInfo(request); 
    213            
    214     // Nested Diagnostic Configurator to identify the client for 
    215         
    216     HttpSession session = request.getSession(true); 
    217         String uid = (String)session.getAttribute(GSXML.USER_ID_ATT); 
    218     if (uid ==null) { 
    219         uid = ""+getNextUserId(); 
    220         session.setAttribute(GSXML.USER_ID_ATT, uid); 
    221     } 
    222     request.setCharacterEncoding("UTF-8"); 
    223     response.setContentType("text/html;charset=UTF-8"); 
    224     PrintWriter out = response.getWriter(); 
    225  
    226     String lang = request.getParameter(GSParams.LANGUAGE); 
    227     if (lang==null || lang.equals("")) { 
    228         // try the session cached lang 
    229         lang = (String)session.getAttribute(GSParams.LANGUAGE); 
    230         if (lang==null || lang.equals("")) { 
    231         // still not set, use the default 
    232         lang = this.default_lang; 
    233         } 
    234     } 
    235      
    236     // set the lang in the session 
    237     session.setAttribute(GSParams.LANGUAGE, lang); 
    238  
    239     String output = request.getParameter(GSParams.OUTPUT); 
    240     if (output==null || output.equals("")) { 
    241         output = "html"; // uses html by default 
    242     } 
    243  
    244     // the request to the receptionist   
    245     Element xml_message = this.doc.createElement(GSXML.MESSAGE_ELEM); 
    246     Element xml_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PAGE, "", lang, uid); 
    247     xml_request.setAttribute(GSXML.OUTPUT_ATT, output); 
    248     xml_message.appendChild(xml_request); 
    249      
    250      
    251     String action = request.getParameter(GSParams.ACTION); 
    252     String subaction = request.getParameter(GSParams.SUBACTION); 
    253     if (action==null || action.equals("")) { 
    254         // should we do all the following stuff if using default page? 
    255         // display the home page  - the default page 
    256         action = "p"; 
    257         subaction = PageAction.HOME_PAGE; 
    258         xml_request.setAttribute(GSXML.ACTION_ATT, action); 
    259         xml_request.setAttribute(GSXML.SUBACTION_ATT, subaction); 
    260          
    261     } else { 
    262      
    263         xml_request.setAttribute(GSXML.ACTION_ATT, action); 
    264         if (subaction != null) { 
    265         xml_request.setAttribute(GSXML.SUBACTION_ATT, subaction); 
    266         } 
    267  
    268         //  create the param list for the greenstone request - includes 
    269         // the params from the current request and any others from the saved session 
    270         Element xml_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER); 
    271         xml_request.appendChild(xml_param_list); 
    272          
    273         Enumeration params = request.getParameterNames(); 
    274         while(params.hasMoreElements()) { 
    275         String name = (String)params.nextElement(); 
    276         if (!name.equals(GSParams.ACTION) && !name.equals(GSParams.SUBACTION) && !name.equals(GSParams.LANGUAGE) && !name.equals(GSParams.OUTPUT)) {// we have already dealt with these  
    277             String value=""; 
    278             String [] values = request.getParameterValues(name); 
    279             value = values[0]; 
    280             if (values.length > 1) { 
    281             for (int i=1; i< values.length; i++) { 
    282                 value += ","+values[i]; 
    283             } 
    284             } 
    285             // either add it to the param list straight away, or save it to the session and add it later 
    286             if (this.params.shouldSave(name)) {          
    287             session.setAttribute(name, value); 
    288             } else {  
    289             Element param = this.doc.createElement(GSXML.PARAM_ELEM); 
    290             param.setAttribute(GSXML.NAME_ATT, name); 
    291             param.setAttribute(GSXML.VALUE_ATT, GSXML.xmlSafe(value)); 
    292             xml_param_list.appendChild(param); 
    293             } 
     337    //  logger.info("should_cache= " + should_cache); 
     338    //clear the collection-specific cache in the session, since we have no way to know whether this session is  
     339    //about the same collection as the last session or not. 
     340    Enumeration attributeNames = session.getAttributeNames(); 
     341    while(attributeNames.hasMoreElements()) { 
     342        String name = (String)attributeNames.nextElement(); 
     343        if (!name.equals (GSXML.USER_SESSION_CACHE_ATT) 
     344                && !name.equals (GSParams.LANGUAGE)  
     345                && !name.equals (GSXML.USER_ID_ATT)) { 
     346            session.removeAttribute(name); 
     347        } 
     348    } 
     349     
     350    UserSessionCache session_cache = null; 
     351    Hashtable param_table = null;     
     352    Hashtable table = null; 
     353    String sid = session.getId(); 
     354    if (should_cache == true && collection != null && !collection.equals("")) { 
     355        String key_str = valid_site_name + collection; 
     356        if (session_ids_table.containsKey(sid)) { 
     357            session_cache = (UserSessionCache)session_ids_table.get(sid); 
     358            param_table = session_cache.getParamsTable(); 
     359            logger.info("collections in table: " + tableToString(param_table)); 
     360                if (param_table.containsKey(key_str)) { 
     361                    //logger.info("existing table: " + collection); 
     362                    table = (Hashtable)param_table.get(key_str); 
     363                } else { 
     364                    table = new Hashtable(); 
     365                    param_table.put(key_str, table); 
     366                    //logger.info("new table: " + collection); 
     367                } 
     368        } else { 
     369            param_table = new Hashtable(); 
     370            table = new Hashtable(); 
     371            param_table.put(key_str, table); 
     372            session_cache = new UserSessionCache(sid, param_table); 
     373            session_ids_table.put(sid, session_cache); 
     374            //logger.info("new session id"); 
     375        } 
     376    } 
     377 
     378    if (action==null || action.equals ("")) { 
     379      // should we do all the following stuff if using default page? 
     380      // display the home page  - the default page 
     381      action = "p"; 
     382      subaction = PageAction.HOME_PAGE; 
     383       
     384      xml_request.setAttribute (GSXML.ACTION_ATT, action); 
     385      xml_request.setAttribute (GSXML.SUBACTION_ATT, subaction); 
     386       
     387    } else { 
     388       
     389      xml_request.setAttribute (GSXML.ACTION_ATT, action); 
     390      if (subaction != null) { 
     391        xml_request.setAttribute (GSXML.SUBACTION_ATT, subaction); 
     392      } 
     393       
     394      //  create the param list for the greenstone request - includes 
     395      // the params from the current request and any others from the saved session 
     396      Element xml_param_list = this.doc.createElement (GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER); 
     397      xml_request.appendChild (xml_param_list); 
     398       
     399      Enumeration params = request.getParameterNames (); 
     400      while(params.hasMoreElements ()) { 
     401        String name = (String)params.nextElement (); 
     402        if (!name.equals (GSParams.ACTION)  
     403                && !name.equals (GSParams.SUBACTION)  
     404                && !name.equals (GSParams.LANGUAGE)  
     405                && !name.equals (GSParams.OUTPUT)) {// we have already dealt with these 
     406          String value=""; 
     407          String [] values = request.getParameterValues (name); 
     408          value = values[0]; 
     409          if (values.length > 1) { 
     410            for (int i=1; i< values.length; i++) { 
     411              value += ","+values[i]; 
     412            } 
     413          } 
     414          // either add it to the param list straight away, or save it to the session and add it later 
     415          if (this.params.shouldSave (name)) { 
     416              if (table != null) {               
     417                  table.put(name, value);                     
     418              } 
     419          } else { 
     420            Element param = this.doc.createElement (GSXML.PARAM_ELEM); 
     421            param.setAttribute (GSXML.NAME_ATT, name); 
     422            param.setAttribute (GSXML.VALUE_ATT, GSXML.xmlSafe (value)); 
     423            xml_param_list.appendChild (param); 
     424          } 
     425        } 
     426      } 
     427      //put everything in the table into the session 
     428      if (table != null) { 
     429          Enumeration keys = table.keys (); 
     430          while(keys.hasMoreElements ()) { 
     431              String name = (String)keys.nextElement(); 
     432              session.setAttribute(name, (String)table.get(name)); 
     433          } 
     434      } 
     435       
     436      // put in all the params from the session cache 
     437      params = session.getAttributeNames (); 
     438      while(params.hasMoreElements ()) { 
     439        String name = (String)params.nextElement (); 
     440         
     441        if ( !name.equals (GSXML.USER_SESSION_CACHE_ATT)  
     442                && !name.equals (GSParams.LANGUAGE)  
     443                && !name.equals (GSXML.USER_ID_ATT)) {  
     444        // lang and uid are stored but we dont want it in the param list cos its already in the request 
     445          Element param = this.doc.createElement (GSXML.PARAM_ELEM); 
     446          param.setAttribute (GSXML.NAME_ATT, name); 
     447          String value =  GSXML.xmlSafe ((String)session.getAttribute (name)); 
     448          // ugly hack to undo : escaping 
     449          value = value.replaceAll ("%3A", "\\:"); 
     450          param.setAttribute (GSXML.VALUE_ATT,value); 
     451          xml_param_list.appendChild (param); 
     452        } 
     453      } 
     454         
     455      //now set the UserSessionCache object into the session with its life expectancy 
     456      if (session_cache != null) { 
     457          session.setAttribute(GSXML.USER_SESSION_CACHE_ATT, session_cache); 
     458          session.setMaxInactiveInterval(session_expiration); 
     459      } 
     460    } 
     461     
     462    if (!output.equals ("html")) { 
     463      response.setContentType ("text/xml"); // for now use text 
     464    } 
     465     
     466    //GSXML.printXMLNode(xml_message); 
     467     
     468    Element xml_result = this.recept.process (xml_message); 
     469    encodeURLs (xml_result, response); 
     470    out.println (this.converter.getPrettyString (xml_result)); 
     471     
     472    displaySize(session_ids_table); 
     473  } 
     474  //a debugging method 
     475  private void displaySize(Hashtable table) { 
     476      if(table == null) { 
     477          logger.info("cached table is null"); 
     478          return; 
     479      } 
     480      if (table.size() == 0) { 
     481          logger.info("cached table size is zero"); 
     482          return; 
     483      } 
     484      int num_cached_coll = 0; 
     485        ArrayList cache_list = new ArrayList(table.values()); 
     486        for (int i=0; i<cache_list.size(); i++) { 
     487            num_cached_coll += ((UserSessionCache)cache_list.get(i)).tableSize();            
    294488        } 
    295         } 
    296          
    297         // put in all the params from the session cache 
    298         params = session.getAttributeNames(); 
    299         while(params.hasMoreElements()) { 
    300         String name = (String)params.nextElement(); 
    301          
    302         if ( !name.equals(GSParams.LANGUAGE) && !name.equals(GSXML.USER_ID_ATT)) { // lang and uid are stored but we dont want it in the param list cos its already in the request 
    303              
    304             Element param = this.doc.createElement(GSXML.PARAM_ELEM); 
    305             param.setAttribute(GSXML.NAME_ATT, name); 
    306             String value =  GSXML.xmlSafe((String)session.getAttribute(name)); 
    307             // ugly hack to undo : escaping 
    308             value = value.replaceAll("%3A", "\\:"); 
    309             param.setAttribute(GSXML.VALUE_ATT,value); 
    310             xml_param_list.appendChild(param); 
    311         } 
    312         } 
    313  
    314      
    315     } 
    316      
    317     if (!output.equals("html")) { 
    318         response.setContentType("text/xml"); // for now use text 
    319     } 
    320  
    321     //GSXML.printXMLNode(xml_message);   
    322  
    323     Element xml_result = this.recept.process(xml_message); 
    324     encodeURLs(xml_result, response); 
    325     out.println(this.converter.getPrettyString(xml_result)); 
    326     } 
    327  
    328     /** this goes through each URL and adds in a session id if needed-- 
    329      * its needed if the browser doesn't accept cookies 
    330      * also escapes things if needed 
    331      */ 
    332     protected void encodeURLs(Element data, HttpServletResponse response) { 
    333      
    334     if (data == null) { 
    335         return; 
    336     } 
    337     // get all the <a> elements 
    338     NodeList hrefs = data.getElementsByTagName("a"); 
    339     for (int i=0; i<hrefs.getLength(); i++) { 
    340         Element a = (Element)hrefs.item(i); 
    341         // ugly hack to get rid of : in the args - interferes with session handling 
    342         String href = a.getAttribute("href"); 
    343         if (!href.equals("")) { 
    344         if (href.indexOf("?")!=-1) { 
    345             String[] parts = href.split("\\?", -1); 
    346             parts[1]=parts[1].replaceAll(":", "%3A"); 
    347             href = parts[0]+"?"+parts[1]; 
    348         } 
    349         a.setAttribute("href", response.encodeURL(href)); 
    350         } 
    351     } 
    352      
    353     // now find any submit bits - get all the <form> elements 
    354     NodeList forms = data.getElementsByTagName("form"); 
    355     for (int i=0; i<forms.getLength(); i++) { 
    356         Element form = (Element)forms.item(i); 
    357         form.setAttribute("action", response.encodeURL(form.getAttribute("action"))); 
    358     } 
    359     // are these the only cases where URLs occur?? 
    360     // we should only do this for greenstone urls? 
    361      
    362     } 
    363  
    364     synchronized protected int getNextUserId() { 
    365     next_user_id++; 
    366     return next_user_id; 
    367     } 
    368  
    369     public void doPost(HttpServletRequest request, 
    370               HttpServletResponse response) 
    371     throws ServletException, IOException { 
    372     doGet(request,response); 
    373  
    374     } 
     489      logger.info("Number of sessions : total number of cached collection info = " + table.size() + " : " + num_cached_coll); 
     490  }   
     491  /** merely a debugging method! */ 
     492  private String tableToString(Hashtable table) { 
     493     String str = ""; 
     494     Enumeration keys = table.keys (); 
     495     while(keys.hasMoreElements ()) { 
     496      String name = (String)keys.nextElement(); 
     497      str += name + ", "; 
     498     } 
     499     return str; 
     500  } 
     501 
     502  /** this goes through each URL and adds in a session id if needed-- 
     503   * its needed if the browser doesn't accept cookies 
     504   * also escapes things if needed 
     505   */ 
     506  protected void encodeURLs(Element data, HttpServletResponse response) { 
     507     
     508    if (data == null) { 
     509      return; 
     510    } 
     511    // get all the <a> elements 
     512    NodeList hrefs = data.getElementsByTagName("a"); 
     513    for (int i=0; i<hrefs.getLength(); i++) { 
     514      Element a = (Element)hrefs.item(i); 
     515      // ugly hack to get rid of : in the args - interferes with session handling 
     516      String href = a.getAttribute("href"); 
     517      if (!href.equals("")) { 
     518        if (href.indexOf("?")!=-1) { 
     519          String[] parts = href.split("\\?", -1); 
     520          parts[1]=parts[1].replaceAll(":", "%3A"); 
     521          href = parts[0]+"?"+parts[1]; 
     522        } 
     523        a.setAttribute("href", response.encodeURL(href)); 
     524      } 
     525    } 
     526     
     527    // now find any submit bits - get all the <form> elements 
     528    NodeList forms = data.getElementsByTagName("form"); 
     529    for (int i=0; i<forms.getLength(); i++) { 
     530      Element form = (Element)forms.item(i); 
     531      form.setAttribute("action", response.encodeURL(form.getAttribute("action"))); 
     532    } 
     533    // are these the only cases where URLs occur?? 
     534    // we should only do this for greenstone urls? 
     535     
     536  } 
     537   
     538  synchronized protected int getNextUserId() { 
     539    next_user_id++; 
     540    return next_user_id; 
     541  } 
     542   
     543  public void doPost(HttpServletRequest request, 
     544    HttpServletResponse response) 
     545    throws ServletException, IOException { 
     546    doGet(request,response); 
     547     
     548  } 
    375549}