Changeset 24019

Show
Ignore:
Timestamp:
17.05.2011 13:20:56 (8 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 modified

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