View Javadoc

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