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.util.*;
009    import java.util.logging.*;
010    import java.io.*;
011    import javax.servlet.*;
012    import javax.servlet.http.*;
013    
014    import fc.io.*;
015    
016    /** 
017    Misc. web related utility functions 
018    
019    @author hursh jain
020    **/
021    public class WebUtil 
022    {
023    final static Log log = Log.get("fc.web.servlet");
024    
025    //--------------------- getParameters ----------------------
026    
027    /** 
028    Gets the specified required initialization parameter from
029    the servlet context. If this param is not found, throws a
030    permanent {@link javax.servlet.UnavailableException}.
031    **/
032    public static final String getRequiredParam
033      (ServletContext context, String name) 
034    throws ServletException
035      {
036      String param = context.getInitParameter(name);    
037    
038      if (param == null) {
039        String error = "Required Servlet Init Parameter: '" + name + "' was not found";
040        log.error(error);
041        throw new UnavailableException(error);
042        }
043    
044      return param; 
045      }
046    
047    /** 
048    Gets the specified initialization parameter from the servlet context. If 
049    this param is not found, then the specified backup value is returned.
050    **/
051    public static final String getParam(
052      ServletContext context, String name, String backup) 
053      {
054      String param = context.getInitParameter(name);    
055      if (param != null)
056        return param; 
057      else
058        return backup;
059      }
060    
061    /** 
062    Gets the specified initialization parameter for the specified servlet
063    (via it's ServletConfig). Note, servlet init parameters are servlet
064    specific whereas context parameters are shared by all servlets within
065    that context. If this param is not found, throws a permanent {@link
066    javax.servlet.UnavailableException}.
067    **/
068    public static final String getRequiredParam(Servlet servlet, String name) 
069    throws ServletException
070      {
071      ServletConfig config = servlet.getServletConfig();
072      String param = config.getInitParameter(name);   
073    
074      if (param == null) {
075        String error = "Required Servlet Init Parameter: '" + name + "' for servlet '" + config.getServletName() + "' was not found";
076        log.error(error);
077        throw new UnavailableException(error);
078        }
079    
080      return param; 
081      }
082    
083    /** 
084    Gets the specified initialization parameter for the specified servlet
085    (via it's ServletConfig). Note, servlet init parameters are servlet
086    specific whereas context parameters are shared by all servlets within
087    that context. If this param is not found, then the specified backup value
088    is returned.
089    **/
090    public static final String getParam(
091      Servlet servlet, String name, String backup) 
092      {
093      ServletConfig config = servlet.getServletConfig();
094      String param = config.getInitParameter(name);   
095      if (param != null)
096        return param; 
097      else
098        return backup;
099      }
100    
101    /** 
102    Gets the specified required parameter from the request
103    object. If this param is not found, throws a ServletException
104    **/
105    public static final String getRequiredParam(
106                HttpServletRequest request, String name) 
107    throws ServletException
108      {
109      String param = request.getParameter(name);    
110    
111      if (param == null) {
112        String error = "Required Parameter: '" + name + "' was not found";
113        log.error(error);
114        throw new ServletException(error);
115        }
116    
117      return param; 
118      }
119    
120    /** 
121    Gets the specified parameter from the request object. 
122    If this param is not found, returns the backup value.
123    **/
124    public static final String getParam(
125      HttpServletRequest request, String name, String backup) 
126      {
127      String param = request.getParameter(name);    
128      if (param != null)
129        return param; 
130      else
131        return backup;
132      }
133    
134    /** 
135    The returned value will be <tt>true</tt> if the specified parameter
136    is present in the request and is a non-null non-empty string (<b>of
137    any value</b>). This is useful for radioboxes and checkboxes.
138    **/
139    public static final boolean isSelected(
140      HttpServletRequest request, String name) 
141      {
142      String param = request.getParameter(name);    
143      if (param == null || param.equals(""))
144        return false;       
145        
146      return true;
147      }
148    
149    /** 
150    Convenience method that returns the specified parameter as a boolean 
151    value. The returned value will be converted via the
152    {@link Boolean#parseBoolean(String)} (for <tt>true</tt>, the 
153    value should be non-null and equal ignore case to "true").
154    **/
155    public static final boolean getBooleanParameter(
156      HttpServletRequest request, String name)
157      {
158      String param = request.getParameter(name);    
159      return Boolean.parseBoolean(param);
160      }
161    
162    
163    //--------------------- getAttributes ----------------------
164      
165    /** 
166    Gets the specified required attribute from the servlet context. If 
167    this attribute is not found, throws a permanent 
168    {@link javax.servlet.UnavailableException}.
169    **/
170    public static final Object getRequiredAttribute(
171      ServletContext context, String name) 
172    throws ServletException
173      {
174      Object param = context.getAttribute(name);    
175    
176      if (param == null) {
177        String error = "Required context attribute: '" + name + "' was not found";
178        log.error(error);
179        throw new UnavailableException(error);  
180        }
181    
182      return param; 
183      }
184    
185    /** 
186    Gets the specified attribute from the servlet context. If this attribute
187    is not found, then the specified backup value is returned.
188    **/
189    public static final Object getAttribute(
190      ServletContext context, String name, String backup) 
191    throws ServletException
192      {
193      Object param = context.getAttribute(name);    
194      
195      if (param != null)    
196        return param; 
197      else
198        return backup;
199      }
200    
201    /** 
202    Gets the specified required attribute from the request object. 
203    If this param is not found, throws a ServletException.
204    **/
205    public static final Object getRequiredAttribute(
206                HttpServletRequest request, String name) 
207    throws ServletException
208      {
209      Object param = request.getAttribute(name);    
210      
211      if (param == null) {
212        String error = "Required Parameter: '" + name + "' was not found";
213        log.error(error);
214        throw new ServletException(error);  
215        }
216    
217      return param; 
218      }
219    
220    /** 
221    Gets the specified attribute from the request object. 
222    If this attribute is not found, returns the backup value.
223    **/
224    public static final Object getAttribute(
225      HttpServletRequest request, String name, String backup) 
226    throws ServletException
227      {
228      Object param = request.getAttribute(name);    
229      if (param != null)
230        return param; 
231      else
232        return backup;
233      }
234    
235    //----------------------------------------------------------
236    
237    /** 
238    Returns a HttpSession attribute as a String or null if the attribute
239    was absent. 
240    
241    @param  name  the name of the session attribute
242    @throws ClassCastException    if the attribute was not a String
243    @throws NullPointerException  if the specified session or name parameters
244                    were null
245    **/ 
246    public static final String getSessionString(HttpSession session, String name) 
247      {
248      Object obj = session.getAttribute(name);
249      if (obj != null)
250        return (String) obj;
251      else
252        return null;
253      }
254    
255    /**
256    Returns the cookie with the specified name or <tt>null</tt> if no cookie
257    was found.
258    */
259    public static Cookie getCookie(HttpServletRequest req, String cookieName)
260      {
261      Cookie[] cookies = req.getCookies();
262      
263      if (cookies == null)
264        return null;
265        
266      for (int n = 0; n < cookies.length; n++) 
267        {
268        if (cookies[n].getName().equals(cookieName))
269          {
270          return cookies[n];
271          }
272        }
273      return null;
274      }
275      
276    /** 
277    Redirects the request (server side redirect) to the specified relative URL
278    via the {@link javax.servlet.ServletRequest#getRequestDispatcher}. See
279    {@link javax.servlet.RequestDispatcher#forward} for restrictions while
280    forwarding to another page (in particular, the response must not have been
281    committed before calling this method).
282    <p>
283    The calling code <b>must</b> have a <tt>return</tt> statement immediately
284    after calling this method, otherwise RequestDispatching will probably not
285    work as intended.
286    
287    @param  req   the current request
288    @param  res   the current response
289    @param  URL   The pathname specified may be relative, although it 
290            cannot extend outside the current servlet context. If the
291            path begins with a "/" it is interpreted as starting from
292            the root of the current context. (i.e., the webapp context,
293            if present, does not need to be specified).
294    **/
295    public static final void forward ( HttpServletRequest req, 
296                       HttpServletResponse res,
297                       String URL)
298    throws ServletException, IOException
299      {
300      RequestDispatcher rd = req.getRequestDispatcher(URL);
301      if (log.canLog(Log.DEBUG)) {
302        StringBuffer buf = getRequestURL(req);
303        log.bug(buf, "forwarding to page: ", URL);
304        }
305      rd.forward(req, res); 
306      }
307    
308    /** 
309    Redirects the browser to the specified URL via a client side redirect URL.
310    Automatically creates a full URL <u>(including the webapp context path)</u>
311    suitable for this purpose. This method is a thin wrapper around {@link
312    javax.servlet.http.HttpServletResponse#sendRedirect Response.sentRedirect} 
313    <p>
314    Session information is preserved if using container provided URL-based sessions. 
315    <p>
316    <u>If the response has already been committed, this method throws an
317    <tt>IllegalStateException</tt></u>. After using this method, the response should be
318    considered to be committed and should not be written to.
319    
320    @param  req     the current request
321    @param  res     the current response
322    @param  location  See 
323              {@link javax.servlet.http.HttpResponse#sendRedirect}.
324              Essentially, the location can be relative to the
325              specified request's URI or relative to the 
326              context root if it contains a leading '/'
327    **/
328    public static final void clientRedirect(
329      HttpServletRequest req, HttpServletResponse res, String location)
330    throws ServletException, IOException
331      {
332      String redirectURL = res.encodeRedirectURL(
333                  absolutePath(req, location));
334      if (log.canLog(Log.DEBUG)) {
335        StringBuffer buf = getRequestURL(req);
336        log.bug(buf, "redirecting to page: ", redirectURL);
337        }   
338      res.sendRedirect(redirectURL);
339      }
340    
341    /** 
342    Creates an absolute path starting from the web document root directory. It
343    does so by prepending the webapp context path (if any) of the specified
344    request to the specified path. The path is <b>not</b> URL encoded with
345    session informtion (see {@link #absoluteEncPath}).
346    <p>
347    This method should be used for all HTML links (in html pages and forms) 
348    and also for client side redirects. This ensures the ability to move the calling code 
349    to a different web app (other than the default root ("/") web app). If
350    it's certain that there will always only be 1 web app (the default)
351    then calling this method is not necessary. 
352    <p>
353    Note also that server-side redirects and includes (with RequestDispatcher)
354    should *not* use this method since all such server side redirects etc
355    automatically work as expected inside the web app context and are always
356    relative to the web app context itself.
357    
358    @param  req   the current HttpServletRequest
359    @param  path  an absolute path starting from the root of
360            the context associated with the request. 
361            If the current webapp (context) is <tt>/foo</tt> and
362            the specified path is <tt>/bar</tt>, then this
363            method will return <tt>/foo/bar</tt>
364    **/
365    public static final String absolutePath(HttpServletRequest req, String path) 
366      {
367      return req.getContextPath() + path;
368      }
369    
370    /** 
371    URL encodes and returns the path obtained via {@link #absolutePath}. 
372    **/
373    public static final String absoluteEncPath(
374      HttpServletRequest req, HttpServletResponse res, String path) 
375      {
376      return res.encodeURL(absolutePath(req, path));
377      }
378      
379    /** 
380    @return the full requested URL including any query parameters.  
381        (the {@link 
382        javax.servlet.Http.HttpServletRequest.getRequestURL() RequestURL}
383        method in HttpServletRequest does not return the query part of the URL)
384    **/
385    public static final StringBuffer getRequestURL(HttpServletRequest req) 
386      {
387      StringBuffer buf =  req.getRequestURL();
388      String qs = req.getQueryString();
389      if (qs !=null) {
390        buf.append('?');
391        buf.append(qs);
392        }
393      return buf;
394      }
395      
396      
397    //== HTML Form related ==========================
398    
399    private static final String confirm = "confirm";
400    private static final String cancel = "cancel";
401    
402    /** 
403    Returns <tt>true</tt> only if a request parameter with the
404    name <tt>confirm</tt> is seen. Forms can set a submit button
405    with this name to signal a confirm request.
406    **/
407    public static final boolean requestCancelled(HttpServletRequest req) {
408      String str = req.getParameter(cancel);
409      return (str != null); //testing for key not value
410      }
411    
412    /** 
413    Returns <tt>true</tt> only if a request parameter with the
414    name <tt>cancel</tt> is seen. Forms can set a submit button
415    with this name to signal a cancel request.
416    **/
417    public static final boolean requestConfirmed(HttpServletRequest req) {
418      String str = req.getParameter(confirm);
419      return (str != null); //testing for key not value
420      }
421      
422    /** 
423    writes all request params received in the specied request to
424    <tt>System.out</tt>. Useful for debugging.
425    **/
426    public static final void debugRequestParams(HttpServletRequest req) {
427      System.out.println("======== Request Params for request=" + req + "===========");
428      Enumeration e = req.getParameterNames();
429      while (e.hasMoreElements()) 
430        {
431            String key = (String)e.nextElement();
432            String[] values = req.getParameterValues(key);
433            System.out.print("   " + key + "=") ;
434        if (values.length == 1) {
435          System.out.print("[" + values[0] + "]");
436          }
437          else {    
438              for(int i = 0; i < values.length; i++) {
439                  System.out.print(" value[" + i + "]=["+values[i] + "]; ");
440              }
441          }
442          System.out.println();
443          }
444      System.out.println("========= End Request Params for request=" + req + "=========\n");
445      }
446      
447    }          //~class WebUtil
448