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
006package fc.web.servlet;
007
008import java.io.*;
009import java.util.logging.*;
010import java.util.*;
011import javax.servlet.*;
012import javax.servlet.http.*;
013
014import fc.io.*;
015import fc.web.*;
016import 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/** 
025Manages various {@link Action} available to a servlet. Subclasses 
026should add and manage appropriate actions.
027
028@author hursh jain
029**/
030public abstract class ActionMgr
031{
032protected final SystemLog log; 
033protected   final Map     actionMap;
034
035/** 
036Constructs a new ActionMgr 
037**/
038protected ActionMgr() 
039  {
040  log = Log.getDefault();
041  actionMap = new HashMap();
042  }
043
044/** 
045Registers an action. Action names are case <u>insensitive</u>.
046**/
047public 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/** 
062Handles a request from a web client. Expects certain parameters to
063be present in the specified <tt>HttpServletRequest</tt>. The main
064parameter 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>
075Various actions expect action-specific parameters via the request
076object parameter. This parameters can be set programatically or via
077the web client and optionally, actions can also return results via 
078setting them in the request object. The documentation for each action
079method should give more detail.
080
081@throws Exception if the action parameter is missing or not understood
082**/
083public void handleWebRequest(HttpServletRequest req, HttpServletResponse res) 
084throws 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  
105public String toString() {
106  return getClass().getName() + "; actions=" + actionMap;
107  }
108
109}          //~class ActionMgr