001    // Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 
002    // The Molly framework is freely distributable under the terms of an
003    // MIT-style license. For details, see the molly pages web site at:
004    // http://www.mollypages.org/. Use, modify, have fun !
005    
006    package fc.web.servlet;
007    
008    import java.io.*;
009    import java.util.logging.*;
010    import java.util.*;
011    import javax.servlet.*;
012    import javax.servlet.http.*;
013    
014    import fc.io.*;
015    import fc.web.*;
016    import fc.util.*;
017    
018    //In the future, java.security should allow us to use logon credentials for
019    //security. Right now, as of jdk 1.4 it seems to be non-trivial to create
020    //and install new security policies based on the current login info. java.security
021    //is really targetted towards code principals i.e, granting *code* various permissions
022    //based on where the code was *loaded* from. 
023    
024    /** 
025    Manages various {@link Action} available to a servlet. Subclasses 
026    should add and manage appropriate actions.
027    
028    @author hursh jain
029    **/
030    public abstract class ActionMgr
031    {
032    protected final SystemLog log; 
033    protected   final Map     actionMap;
034    
035    /** 
036    Constructs a new ActionMgr 
037    **/
038    protected ActionMgr() 
039      {
040      log = Log.getDefault();
041      actionMap = new HashMap();
042      }
043    
044    /** 
045    Registers an action. Action names are case <u>insensitive</u>.
046    **/
047    public final void addAction(Action action) 
048      {
049      //log.entering("ActionMgr", "addAction"); 
050      
051      String name = action.getName().toLowerCase();
052      
053      if (actionMap.containsKey(name)) {
054        throw new IllegalArgumentException("An action with the name '" + name + " already exists"); 
055        }
056      actionMap.put(name, action);
057      
058      log.bug("ActionMgr: installed new action=", name);
059      }
060    
061    /** 
062    Handles a request from a web client. Expects certain parameters to
063    be present in the specified <tt>HttpServletRequest</tt>. The main
064    parameter needed by this method is:
065    <blockquote>
066    <ul>
067      <li>Param name:<tt>act</tt><br>
068      Param value: A case-insenstive class name of the {@link Action}
069        class that will be invoked (for example: "showdir"). Case is not
070        important but using all lower case names will save a few machine 
071      cycles. This should match the name with which a particular action
072      object was constructed.
073    </ul>
074    </blockquote>
075    Various actions expect action-specific parameters via the request
076    object parameter. This parameters can be set programatically or via
077    the web client and optionally, actions can also return results via 
078    setting them in the request object. The documentation for each action
079    method should give more detail.
080    
081    @throws Exception if the action parameter is missing or not understood
082    **/
083    public void handleWebRequest(HttpServletRequest req, HttpServletResponse res) 
084    throws Exception
085      {
086      log.bug("enter");
087      if (log.canLog(SystemLog.DEBUG)) {
088        log.bug("requested URL=" + WebUtil.getRequestURL(req), "req=", req);
089        }
090      String actionName = WebUtil.getRequiredParam(req, "act").toLowerCase();
091        
092      Action action = null;
093      if (actionMap.containsKey(actionName)) {
094        action = (Action) actionMap.get(actionName);
095        }
096      else { //action not found
097        log.warn("Could not find action for action=" + action, "installed actions=", actionMap);
098        throw new ServletException("ActionMgr: Could not understand the web request, request=" + req);  
099        }
100      
101      action.handle(req, res);  //the op will extract further params as needed
102      log.bug("exit");
103      }
104      
105    public String toString() {
106      return getClass().getName() + "; actions=" + actionMap;
107      }
108    
109    }          //~class ActionMgr