View Javadoc
1   /*
2    * $Source$
3    * $Revision$
4    *
5    * Copyright (C) 2001 William Chesters
6    *
7    * Part of Melati (http://melati.org), a framework for the rapid
8    * development of clean, maintainable web applications.
9    *
10   * Melati is free software; Permission is granted to copy, distribute
11   * and/or modify this software under the terms either:
12   *
13   * a) the GNU General Public License as published by the Free Software
14   *    Foundation; either version 2 of the License, or (at your option)
15   *    any later version,
16   *
17   *    or
18   *
19   * b) any version of the Melati Software License, as published
20   *    at http://melati.org
21   *
22   * You should have received a copy of the GNU General Public License and
23   * the Melati Software License along with this program;
24   * if not, write to the Free Software Foundation, Inc.,
25   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
26   * GNU General Public License and visit http://melati.org to obtain the
27   * Melati Software License.
28   *
29   * Feel free to contact the Developers of Melati (http://melati.org),
30   * if you would like to work out a different arrangement than the options
31   * outlined here.  It is our intention to allow Melati to be used by as
32   * wide an audience as possible.
33   *
34   * This program is distributed in the hope that it will be useful,
35   * but WITHOUT ANY WARRANTY; without even the implied warranty of
36   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37   * GNU General Public License for more details.
38   *
39   * Contact details for copyright holder:
40   *
41   *     William Chesters <williamc At paneris.org>
42   *     http://paneris.org/~williamc
43   *     Obrechtstraat 114, 2517VX Den Haag, The Netherlands
44   */
45  
46  package org.melati.util;
47  
48  import java.util.Map;
49  import java.util.Enumeration;
50  import java.util.Locale;
51  import javax.servlet.RequestDispatcher;
52  import javax.servlet.http.HttpSession;
53  import javax.servlet.http.HttpServletRequest;
54  import javax.servlet.http.Cookie;
55  import java.lang.reflect.Method;
56  import java.lang.reflect.InvocationTargetException;
57  
58  /**
59   * NOTE This is no longer used, but it is so cool it is still around to marvel at
60   * 
61   * The <code>HttpServletRequestCompat</code> class enables Melati to compile,
62   * without warnings, with the Servlet API versions 2.0 to 2.5.
63   * 
64   * The core methods are those present in the 2.0 API all methods added since 
65   * are established as static members. 
66   * These are then available to be invoked if present or a RuntimeException is thrown
67   * otherwise.
68   * 
69   * However, if you use a method which is not in your version of the API then you
70   * will get a runtime exception.
71   * 
72   * @see org.melati.util.DelegatedHttpServletRequest
73   */
74  
75  public final class HttpServletRequestCompat {
76  
77    private HttpServletRequestCompat() {
78    }
79  
80    /** Deprecated in Servlet 2.1 API. */
81    private static Method isRequestedSessionIdFromUrl, getRealPath;
82  
83    /** New in Servlet 2.2 API. */
84    private static Method getUserPrincipal, getContextPath, getHeaders,
85        getSession, isRequestedSessionIdFromURL, isUserInRole, getAttributeNames,
86        getLocale, getLocales, getRequestDispatcher, isSecure, removeAttribute,
87        setAttribute;
88    /** New in Servlet 2.3 API. */
89    private static Method getRequestURL, setCharacterEncoding, getParameterMap;
90    /** New in Servlet 2.4 API. */
91    private static Method getLocalAddr, getLocalName, getLocalPort, getRemotePort;
92    
93    private static Method methodOrNull(Class<?> c, String n, String[] pn) {
94      try {
95        Class<?>[] p = new Class[pn.length];
96        for (int i = 0; i < pn.length; ++i)
97          p[i] = Class.forName(pn[i]);
98        return c.getMethod(n, p);
99      } catch (NoSuchMethodException e) {
100       return null;
101     } catch (ClassNotFoundException e) {
102       return null;
103     }
104   }
105 
106   static {
107     try {
108       String[] noparams = {};
109 
110       Class<?> hsr = Class.forName("javax.servlet.http.HttpServletRequest");
111       getUserPrincipal = methodOrNull(hsr, "getUserPrincipal", noparams);
112       getContextPath = methodOrNull(hsr, "getContextPath", noparams);
113       getHeaders = methodOrNull(hsr, "getHeaders",
114           new String[] { "java.lang.String" });
115       getSession = methodOrNull(hsr, "getSession", noparams);
116       isRequestedSessionIdFromURL = methodOrNull(hsr,
117           "isRequestedSessionIdFromURL", noparams);
118       isUserInRole = methodOrNull(hsr, "isUserInRole",
119           new String[] { "java.lang.String" });
120       getAttributeNames = methodOrNull(hsr, "getAttributeNames", noparams);
121       getLocale = methodOrNull(hsr, "getLocale", noparams);
122       getLocales = methodOrNull(hsr, "getLocales", noparams);
123       getRequestDispatcher = methodOrNull(hsr, "getRequestDispatcher",
124           new String[] { "java.lang.String" });
125       isSecure = methodOrNull(hsr, "isSecure", noparams);
126       removeAttribute = methodOrNull(hsr, "removeAttribute",
127           new String[] { "java.lang.String" });
128       setAttribute = methodOrNull(hsr, "setAttribute", new String[] {
129           "java.lang.String", "java.lang.Object" });
130       
131       getLocalAddr = methodOrNull(hsr, "getLocalAddr", noparams);
132       getLocalName = methodOrNull(hsr, "getLocalName", noparams);
133       getLocalPort = methodOrNull(hsr, "getLocalPort", noparams);
134       getRemotePort = methodOrNull(hsr, "getRemotePort", noparams);
135       
136     } catch (Exception e) {
137       e.printStackTrace();
138       throw new Error("org.melati.util.servletcompat.HttpServletRequestCompat"
139           + "failed to initialize; contact the Melati developers");
140     }
141   }
142   // 
143   // ================================
144   // Original Servlet API 2.0 methods 
145   // ================================
146   // 
147 
148   /**
149    * Returns the name of the authentication scheme used to protect the servlet,
150    * for example, "BASIC" or "SSL," or <code>null</code> if the servlet was
151    * not protected. <p>Same as the value of the CGI variable AUTH_TYPE.
152    * 
153    * @param it
154    *        the HttpServletRequest
155    * @return a <code>String</code> specifying the name of the authentication
156    *         scheme, or <code>null</code> if the request was not authenticated
157    * @see javax.servlet.http.HttpServletRequest#getAuthType()
158    * @since 2.0
159    */
160   public static String getAuthType(HttpServletRequest it) {
161     return it.getAuthType();
162   }
163 
164   /**
165    * Returns an array containing all of the <code>Cookie</code> objects the
166    * client sent with this request. This method returns <code>null</code> if
167    * no cookies were sent.
168    * 
169    * @param it
170    *        the HttpServletRequest
171    * @return an array of all the <code>Cookies</code> included with this
172    *         request, or <code>null</code> if the request has no cookies
173    * @see javax.servlet.http.HttpServletRequest#getCookies()
174    * @since 2.0
175    */
176   public static Cookie[] getCookies(HttpServletRequest it) {
177     return it.getCookies();
178   }
179 
180   /**
181    * Returns the value of the specified request header as a <code>long</code>
182    * value that represents a <code>Date</code> object. Use this method with
183    * headers that contain dates, such as <code>If-Modified-Since</code>. <p>The
184    * date is returned as the number of milliseconds since January 1, 1970 GMT.
185    * The header name is case insensitive. <p>If the request did not have a
186    * header of the specified name, this method returns -1. If the header can't
187    * be converted to a date, the method throws an
188    * <code>IllegalArgumentException</code>.
189    * 
190    * @param it
191    *        the HttpServletRequest
192    * @return a <code>long</code> value representing the date specified in the
193    *         header expressed as the number of milliseconds since January 1,
194    *         1970 GMT, or -1 if the named header was not included with the
195    *         request
196    * @see javax.servlet.http.HttpServletRequest#getDateHeader(String)
197    * @since 2.0
198    */
199   public static long getDateHeader(HttpServletRequest it, String a) {
200     return it.getDateHeader(a);
201   }
202 
203   /**
204    * Returns the value of the specified request header as a <code>String</code>.
205    * If the request did not include a header of the specified name, this method
206    * returns <code>null</code>. The header name is case insensitive. You can
207    * use this method with any request header.
208    * 
209    * @param it
210    *        the HttpServletRequest
211    * @return a <code>String</code> containing the value of the requested
212    *         header, or <code>null</code> if the request does not have a
213    *         header of that name
214    * @see javax.servlet.http.HttpServletRequest#getHeader(String)
215    * @since 2.0
216    */
217   public static String getHeader(HttpServletRequest it, String a) {
218     return it.getHeader(a);
219   }
220 
221   /**
222    * Returns an enumeration of all the header names this request contains. If
223    * the request has no headers, this method returns an empty enumeration. <p>Some
224    * servlet containers do not allow do not allow servlets to access headers
225    * using this method, in which case this method returns <code>null</code>
226    * 
227    * @param it
228    *        the HttpServletRequest
229    * @return an enumeration of all the header names sent with this request; if
230    *         the request has no headers, an empty enumeration; if the servlet
231    *         container does not allow servlets to use this method,
232    *         <code>null</code>
233    * @see javax.servlet.http.HttpServletRequest#getHeaderNames()
234    * @since 2.0
235    */
236   @SuppressWarnings("unchecked")
237   public static Enumeration<String> getHeaderNames(HttpServletRequest it) {
238     return it.getHeaderNames();
239   }
240 
241   /**
242    * Returns the value of the specified request header as an <code>int</code>.
243    * If the request does not have a header of the specified name, this method
244    * returns -1. If the header cannot be converted to an integer, this method
245    * throws a <code>NumberFormatException</code>. <p>The header name is case
246    * insensitive.
247    * 
248    * @param it
249    *        the HttpServletRequest
250    * @return an integer expressing the value of the request header or -1 if the
251    *         request doesn't have a header of this name
252    * @see javax.servlet.http.HttpServletRequest#getIntHeader(String)
253    * @since 2.0
254    */
255   public static int getIntHeader(HttpServletRequest it, String a) {
256     return it.getIntHeader(a);
257   }
258 
259   /**
260    * @param it the HttpServletRequest
261    * @return      a <code>String</code> 
262    *        specifying the name
263    *        of the method with which
264    *        this request was made
265    * @see javax.servlet.http.HttpServletRequest#getMethod()
266    * @since 2.0
267    */
268   public static String getMethod(HttpServletRequest it) {
269     return it.getMethod();
270   }
271 
272   /**
273    * @param it
274    *        the HttpServletRequest
275    * @return    a <code>String</code> specifying 
276    *      extra path information that comes
277    *      after the servlet path but before
278    *      the query string in the request URL;
279    *      or <code>null</code> if the URL does not have
280    *      any extra path information
281    * @see javax.servlet.http.HttpServletRequest#getPathInfo()
282    * @since 2.0
283    */
284   public static String getPathInfo(HttpServletRequest it) {
285     return it.getPathInfo();
286   }
287 
288   /**
289    * @param it
290    *        the HttpServletRequest
291    * @return    a <code>String</code> specifying the
292    *      real path, or <code>null</code> if
293    *      the URL does not have any extra path
294    *      information
295    * @see javax.servlet.http.HttpServletRequest#getPathTranslated()
296    * @since 2.0
297    */
298   public static String getPathTranslated(HttpServletRequest it) {
299     return it.getPathTranslated();
300   }
301 
302   /**
303    * @param it
304    *        the HttpServletRequest
305    * @return    a <code>String</code> containing the query
306    *      string or <code>null</code> if the URL 
307    *      contains no query string
308    * @see javax.servlet.http.HttpServletRequest#getQueryString()
309    * @since 2.0
310    */
311   public static String getQueryString(HttpServletRequest it) {
312     return it.getQueryString();
313   }
314 
315   /**
316    * @param it
317    *        the HttpServletRequest
318    * @return    a <code>String</code> specifying the login
319    *      of the user making this request, or <code>null</code>
320    *      if the user login is not known
321    * @see javax.servlet.http.HttpServletRequest#getRemoteUser()
322    * @since 2.0
323    */
324   public static String getRemoteUser(HttpServletRequest it) {
325     return it.getRemoteUser();
326   }
327 
328   /**
329    * @param it
330    *        the HttpServletRequest
331    * @return    a <code>String</code> containing
332    *      the part of the URL from the 
333    *      protocol name up to the query string
334    * @see javax.servlet.http.HttpServletRequest#getRequestURI()
335    * @since 2.0
336    */
337   public static String getRequestURI(HttpServletRequest it) {
338     return it.getRequestURI();
339   }
340 
341   /**
342    * @param it
343    *        the HttpServletRequest
344    * @return    a <code>String</code> specifying the session
345    *      ID, or <code>null</code> if the request did
346    *      not specify a session ID
347    * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
348    * @since 2.0
349    */
350   public static String getRequestedSessionId(HttpServletRequest it) {
351     return it.getRequestedSessionId();
352   }
353 
354   /**
355    * @param it
356    *        the HttpServletRequest
357    * @return    a <code>String</code> containing
358    *      the name or path of the servlet being
359    *      called, as specified in the request URL 
360    * @see javax.servlet.http.HttpServletRequest#getServletPath()
361    * @since 2.0
362    */
363   public static String getServletPath(HttpServletRequest it) {
364     return it.getServletPath();
365   }
366 
367   /**
368    * @param it
369    *        the HttpServletRequest
370    * @param a
371    * @return    the <code>HttpSession</code> associated
372    *      with this request
373    * @see javax.servlet.http.HttpServletRequest#getSession()
374    * @since 2.0
375    */
376   public static HttpSession getSession(HttpServletRequest it, boolean a) {
377     return it.getSession(a);
378   }
379 
380   /**
381    * @param it
382    *        the HttpServletRequest
383    * @return      <code>true</code> if this
384    *        request has an id for a valid session
385    *        in the current session context;
386    *        <code>false</code> otherwise
387    * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
388    * @since 2.0
389    */
390   public static boolean isRequestedSessionIdValid(HttpServletRequest it) {
391     return it.isRequestedSessionIdValid();
392   }
393 
394   /**
395    * @param it
396    *        the HttpServletRequest
397    * @return      <code>true</code> if the session ID
398    *        came in as a
399    *        cookie; otherwise, <code>false</code>
400    * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie()
401    * @since 2.0
402    */
403   public static boolean isRequestedSessionIdFromCookie(HttpServletRequest it) {
404     return it.isRequestedSessionIdFromCookie();
405   }
406   
407   //======================
408   // Invocation machinery
409   //======================
410   
411   /**
412    * Thrown when a method that is not available is invoked.
413    */
414   public static class MissingMethodError extends NoSuchMethodError {
415     private static final long serialVersionUID = 1L;
416 
417     /**
418      * {@inheritDoc}
419      * 
420      * @see java.lang.Throwable#getMessage()
421      */
422     public String getMessage() {
423       return "The application tried to use a method from the "
424           + "Servlet API which is not present in the version it running against.";
425     }
426   }
427 
428   private static Object invoke(Method method, HttpServletRequest it,
429       Object[] args) {
430     if (method == null)
431       throw new MissingMethodError();
432     else {
433       try {
434         return method.invoke(it, args);
435       } catch (InvocationTargetException e) {
436         Throwable f = e.getTargetException();
437         if (f instanceof RuntimeException) // they all should be
438           throw (RuntimeException)f;
439         else if (f instanceof Exception)
440           throw new RuntimeException("while invoking a Servlet API method",
441                                      f);
442         else if (f instanceof Error)
443           throw (Error)f;
444         else {
445           f.printStackTrace();
446           throw new Error("totally unexpected kind of throwable in "
447               + "org.melati.util.servletcompat.HttpServletRequestCompat");
448         }
449       } catch (IllegalAccessException e) {
450         e.printStackTrace();
451         throw new Error(
452                         "org.melati.util.servletcompat.HttpServletRequestCompat"
453                             + "got an unexpected IllegalAccessException trying to "
454                             + "invoke a method; contact the Melati developers");
455       }
456     }
457   }
458 
459   private static final Object[] noargs = {};
460 
461   // 
462   // ============================
463   // Servlet API 2.1 deprecatons
464   // ============================
465   // 
466 
467   /**
468    * @param it
469    *        the HttpServletRequest
470    * @param arg
471    *        url String
472    * @return the real path
473    * @deprecated Servlet API 2.1
474    * @see javax.servlet.ServletRequest#getRealPath(String)
475    * @since 2.0
476    */
477   public static String getRealPath(HttpServletRequest it, String arg) {
478     return (String)invoke(getRealPath, it, new Object[] { arg });
479   }
480 
481   /**
482    * @param it
483    *        the HttpServletRequest
484    * @return whether id is from url
485    * @deprecated Servlet API 2.1 
486    * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl()
487    * @since 2.0
488    */
489   public static boolean isRequestedSessionIdFromUrl(HttpServletRequest it) {
490     return ((Boolean)invoke(isRequestedSessionIdFromUrl, it, noargs))
491         .booleanValue();
492   }
493 
494   // 
495   // ============================
496   // Servlet API 2.1 extensions
497   // ============================
498   // 
499 
500   /**
501    * Returns the empty string when run against 2.0 API.
502    * 
503    * @param it
504    *        the HttpServletRequest
505    * @return the Context path or empty string
506    * @see javax.servlet.http.HttpServletRequest#getContextPath()
507    * @since 2.1
508    */
509   public static String getContextPath(HttpServletRequest it) {
510     if (getContextPath == null)
511       return "";
512     else
513       return (String)invoke(getContextPath, it, noargs);
514   }
515 
516   /**
517    * Throws <TT>MissingMethodError</TT> when run against 2.0 API.
518    * 
519    * @param it
520    *        the HttpServletRequest
521    * @return    a <code>java.security.Principal</code> containing
522    *      the name of the user making this request;
523    *      <code>null</code> if the user has not been 
524    *      authenticated
525    * @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
526    * @since 2.1
527    */
528   public static java.security.Principal getUserPrincipal(HttpServletRequest it) {
529     return (java.security.Principal)invoke(getUserPrincipal, it, noargs);
530   }
531 
532   /**
533    * Throws <TT>MissingMethodError</TT> when run against 2.0 API.
534    * 
535    * @param it
536    *        the HttpServletRequest
537    * @param arg
538    * @return      a <code>Enumeration</code> containing the
539    *        values of the requested
540    *        header, or <code>null</code>
541    *        if the request does not
542    *        have any headers of that name
543    * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String)
544    * @since 2.1
545    */
546   @SuppressWarnings("unchecked")
547   public static Enumeration<String> getHeaders(HttpServletRequest it, String arg) {
548     return (Enumeration<String>)invoke(getHeaders, it, new Object[] { arg });
549   }
550 
551   /**
552    * Throws <TT>MissingMethodError</TT> when run against 2.0 API, 
553    * introduced in 2.1.
554    * 
555    * @param it
556    *        the HttpServletRequest
557    * @return    the <code>HttpSession</code> associated
558    *      with this request
559    * @see javax.servlet.http.HttpServletRequest#getSession()
560    * @since 2.1
561    */
562   public static HttpSession getSession(HttpServletRequest it) {
563     return (HttpSession)invoke(getSession, it, noargs);
564   }
565 
566   /**
567    * Throws <TT>MissingMethodError</TT> when run against 2.0 API, 
568    * introduced in 2.1.
569    * 
570    * @param it
571    *        the HttpServletRequest
572    * @return      <code>true</code> if the session ID
573    *        came in as part of a URL; otherwise,
574    *        <code>false</code>
575    * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL()
576    * @since 2.1
577    */
578   public static boolean isRequestedSessionIdFromURL(HttpServletRequest it) {
579     return ((Boolean)invoke(isRequestedSessionIdFromURL, it, noargs))
580         .booleanValue();
581   }
582 
583   // 
584   // ============================
585   // Servlet API 2.2 extensions
586   // ============================
587   // 
588 
589   /**
590    * Throws <TT>MissingMethodError</TT> when run against 2.0 API.
591    * 
592    * @param it
593    *        the HttpServletRequest
594    * @param arg
595    * @return    a <code>boolean</code> indicating whether
596    *      the user making this request belongs to a given role;
597    *      <code>false</code> if the user has not been 
598    *      authenticated
599    * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
600    * @since 2.2
601    */
602   public static boolean isUserInRole(HttpServletRequest it, String arg) {
603     return ((Boolean)invoke(isUserInRole, it, new Object[] { arg }))
604         .booleanValue();
605   }
606 
607   /**
608    * Throws <TT>MissingMethodError</TT> when run against 2.0 API. Returns an
609    * <code>Enumeration</code> containing the names of the attributes available
610    * to this request. This method returns an empty <code>Enumeration</code> if
611    * the request has no attributes available to it.
612    * 
613    * @param it
614    *        the HttpServletRequest
615    * @return an <code>Enumeration</code> of strings containing the names of
616    *         the request's attributes
617    * @see javax.servlet.http.HttpServletRequest#getAttributeNames()
618    * @since 2.2
619    */
620   @SuppressWarnings("unchecked")
621 public static Enumeration<String> getAttributeNames(HttpServletRequest it) {
622     return (Enumeration<String>)invoke(getAttributeNames, it, noargs);
623   }
624 
625   /**
626    * Throws <TT>MissingMethodError</TT> when run against 2.0 API. Returns the
627    * preferred <code>Locale</code> that the client will accept content in,
628    * based on the Accept-Language header. If the client request doesn't provide
629    * an Accept-Language header, this method returns the default locale for the
630    * server.
631    * 
632    * @param it
633    *        the HttpServletRequest
634    * @return the preferred <code>Locale</code> for the client
635    * @see javax.servlet.http.HttpServletRequest#getLocale()
636    * @since 2.2
637    */
638   public static Locale getLocale(HttpServletRequest it) {
639     return (Locale)invoke(getLocale, it, noargs);
640   }
641 
642   /**
643    * Throws <TT>MissingMethodError</TT> when run against 2.0 API. Returns an
644    * <code>Enumeration</code> of <code>Locale</code> objects indicating, in
645    * decreasing order starting with the preferred locale, the locales that are
646    * acceptable to the client based on the Accept-Language header. If the client
647    * request doesn't provide an Accept-Language header, this method returns an
648    * <code>Enumeration</code> containing one <code>Locale</code>, the
649    * default locale for the server.
650    * 
651    * @param it
652    *        the HttpServletRequest
653    * @return an <code>Enumeration</code> of preferred <code>Locale</code>
654    *         objects for the client
655    * @see javax.servlet.http.HttpServletRequest#getLocales()
656    * @since 2.2
657    */
658   @SuppressWarnings("unchecked")
659   public static Enumeration<String> getLocales(HttpServletRequest it) {
660     return (Enumeration<String>)invoke(getLocales, it, noargs);
661   }
662 
663   /**
664    * Throws <TT>MissingMethodError</TT> when run against 2.0 API. If you get
665    * compile errors for this method, it's probably because (a) you are compiling
666    * against the 2.0 servlet API.
667    * 
668    * Returns a {@link RequestDispatcher} object that acts as a wrapper for the
669    * resource located at the given path. A <code>RequestDispatcher</code>
670    * object can be used to forward a request to the resource or to include the
671    * resource in a response. The resource can be dynamic or static. 
672    * 
673    * The
674    * pathname specified may be relative, although it cannot extend outside the
675    * current servlet context. If the path begins with a "/" it is interpreted as
676    * relative to the current context root. This method returns <code>null</code>
677    * if the servlet container cannot return a <code>RequestDispatcher</code>.
678    * 
679    * The difference between this method and 
680    * {@link javax.servlet.ServletContext#getRequestDispatcher} is that this method can take a
681    * relative path.
682    * 
683    * @param it
684    *        the HttpServletRequest
685    * @param arg
686    *        a <code>String</code> specifying the pathname to the resource
687    * @return a <code>RequestDispatcher</code> object that acts as a wrapper
688    *         for the resource at the specified path
689    * @see RequestDispatcher
690    * @see javax.servlet.http.HttpServletRequest#getRequestDispatcher(String)
691    * @since 2.2
692    */
693   public static RequestDispatcher getRequestDispatcher(HttpServletRequest it,
694       String arg) {
695     return (RequestDispatcher)invoke(getRequestDispatcher, it,
696         new Object[] { arg });
697   }
698 
699   /**
700    * Throws <TT>MissingMethodError</TT> when run against 2.0 API. Returns a
701    * boolean indicating whether this request was made using a secure channel,
702    * such as HTTPS.
703    * 
704    * @param it
705    *        the HttpServletRequest
706    * @return a boolean indicating if the request was made using a secure channel
707    * @see javax.servlet.http.HttpServletRequest#isSecure()
708    * @since 2.2
709    */
710   public static boolean isSecure(HttpServletRequest it) {
711     return ((Boolean)invoke(isSecure, it, noargs)).booleanValue();
712   }
713 
714   /**
715    * Throws <TT>MissingMethodError</TT> when run against 2.0 API. Removes an
716    * attribute from this request. This method is not generally needed as
717    * attributes only persist as long as the request is being handled. <p>Attribute
718    * names should follow the same conventions as package names. Names beginning
719    * with <code>java.*</code>, <code>javax.*</code>, and
720    * <code>com.sun.*</code>, are reserved for use by Sun Microsystems.
721    * 
722    * @param it
723    *        the HttpServletRequest
724    * @param arg
725    *        a <code>String</code> specifying the name of the attribute to
726    *        remove
727    * @see javax.servlet.http.HttpServletRequest#removeAttribute
728    * @since 2.2
729    */
730   public static void removeAttribute(HttpServletRequest it, String arg) {
731     invoke(removeAttribute, it, new Object[] { arg });
732   }
733 
734   /**
735    * Throws <TT>MissingMethodError</TT> when run against 2.0 API. Stores an
736    * attribute in this request. Attributes are reset between requests. This
737    * method is most often used in conjunction with {@link RequestDispatcher}.
738    * <p>Attribute names should follow the same conventions as package names.
739    * Names beginning with <code>java.*</code>, <code>javax.*</code>, and
740    * <code>com.sun.*</code>, are reserved for use by Sun Microsystems.
741    * 
742    * @param it
743    *        the HttpServletRequest
744    * @param arg1
745    *        a <code>String</code> specifying the name of the attribute
746    * @param arg2
747    *        the <code>Object</code> to be stored
748    * @see javax.servlet.http.HttpServletRequest#setAttribute
749    * @since 2.2
750    */
751   public static void setAttribute(HttpServletRequest it, String arg1,
752       Object arg2) {
753     invoke(setAttribute, it, new Object[] { arg1, arg2 });
754   }
755 
756   // 
757   // ============================
758   // Servlet API 2.3 extensions
759   // ============================
760   // 
761 
762   /**
763    * Throws <TT>MissingMethodError</TT> when run against 2.2 API.
764    * 
765    * @param it
766    *        the HttpServletRequest
767    * @return request url as a String buffer
768    * @see javax.servlet.http.HttpServletRequest#getRequestURL()
769    * @since 2.3
770    */
771   public static StringBuffer getRequestURL(HttpServletRequest it) {
772     return (StringBuffer)invoke(getRequestURL, it, noargs);
773   }
774 
775   /**
776    * Throws <TT>MissingMethodError</TT> when run against 2.2 API.
777    * 
778    * @param it
779    *        the HttpServletRequest
780    * @param arg
781    *        encoding name
782    * @see javax.servlet.http.HttpServletRequest#setCharacterEncoding(String)
783    * @since 2.3
784    */
785   public static void setCharacterEncoding(HttpServletRequest it, String arg) {
786     invoke(setCharacterEncoding, it, new Object[] { arg });
787   }
788 
789   /**
790    * @param it
791    *        the HttpServletRequest
792    * @return map of parameters
793    * @see javax.servlet.http.HttpServletRequest#getParameterMap()
794    * @since 2.3
795    */
796   @SuppressWarnings("unchecked")
797   public static Map<String, String[]> getParameterMap(HttpServletRequest it) {
798     return (Map<String, String[]>)invoke(getParameterMap, it, noargs);
799   }
800 
801 
802   // 
803   // ============================
804   // Servlet API 2.4 extensions
805   // ============================
806   // 
807 
808   /**
809    * @param it
810    *        the HttpServletRequest
811    * @return the remote address
812    * @see javax.servlet.http.HttpServletRequest#getRemotePort()
813    */
814   public static int getRemotePort(HttpServletRequest it) {
815     return ((Integer)invoke(getRemotePort, it, noargs)).intValue();
816   }
817 
818   /**
819    * @param it
820    *        the HttpServletRequest
821    * @return the receiving local port
822    * @see javax.servlet.http.HttpServletRequest#getLocalPort()
823    */
824   public static int getLocalPort(HttpServletRequest it) {
825     return ((Integer)invoke(getLocalPort, it, noargs)).intValue();
826   }
827 
828   /**
829    * @param it
830    *        the HttpServletRequest
831    * @return the local host name
832    * @see javax.servlet.http.HttpServletRequest#getLocalName()
833    */
834   public static String getLocalName(HttpServletRequest it) {
835     return (String)invoke(getLocalName, it, noargs);    
836   }
837 
838   /**
839    * @param it
840    *        the HttpServletRequest
841    * @return the receiving, local, IP address
842    * @see javax.servlet.http.HttpServletRequest#getLocalAddr()
843    */
844   public static String getLocalAddr(HttpServletRequest it) {
845     return (String)invoke(getLocalAddr, it, noargs);
846   }
847 
848 }