View Javadoc

1   /*
2    * Copyright 1999,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  
18  package org.apache.commons.messagelet.impl;
19  
20  
21  import java.io.BufferedReader;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.InputStreamReader;
25  import java.io.UnsupportedEncodingException;
26  import java.util.ArrayList;
27  import java.util.Enumeration;
28  import java.util.HashMap;
29  import java.util.Locale;
30  import java.util.Map;
31  
32  import javax.servlet.RequestDispatcher;
33  import javax.servlet.ServletContext;
34  import javax.servlet.ServletInputStream;
35  import javax.servlet.ServletRequest;
36  
37  import org.apache.commons.collections.iterators.IteratorEnumeration;
38  import org.apache.commons.collections.iterators.SingletonIterator;
39  
40  /**
41   * Based on the RequestBase code from Catalina.
42   *
43   * @author Craig R. McClanahan
44   * @author James Strachan
45   * @version $Revision: 155459 $ $Date: 2005-02-26 13:24:44 +0000 (Sat, 26 Feb 2005) $
46   */
47  
48  public class ServletRequestImpl implements ServletRequest {
49  
50  
51      // ----------------------------------------------------- Instance Variables
52  
53  
54      /**
55       * The attributes associated with this Request, keyed by attribute name.
56       */
57      protected HashMap attributes = new HashMap();
58  
59  
60      /**
61       * The authorization credentials sent with this Request.
62       */
63      protected String authorization = null;
64  
65  
66      /**
67       * The character encoding for this Request.
68       */
69      protected String characterEncoding = null;
70  
71  
72  
73      /**
74       * The content length associated with this request.
75       */
76      protected int contentLength = -1;
77  
78  
79      /**
80       * The content type associated with this request.
81       */
82      protected String contentType = null;
83  
84  
85      /**
86       * The default Locale if none are specified.
87       */
88      protected static Locale defaultLocale = Locale.getDefault();
89  
90  
91      /**
92       * The input stream associated with this Request.
93       */
94      protected InputStream input = null;
95  
96  
97      /**
98       * The preferred Locales assocaited with this Request.
99       */
100     protected ArrayList locales = new ArrayList();
101 
102 
103 
104     /**
105      * The protocol name and version associated with this Request.
106      */
107     protected String protocol = null;
108 
109 
110     /**
111      * The reader that has been returned by <code>getReader</code>, if any.
112      */
113     protected BufferedReader reader = null;
114 
115 
116     /**
117      * The remote address associated with this request.
118      */
119     protected String remoteAddr = null;
120 
121 
122     /**
123      * The fully qualified name of the remote host.
124      */
125     protected String remoteHost = null;
126 
127 
128 
129     /**
130      * The scheme associated with this Request.
131      */
132     protected String scheme = null;
133 
134 
135     /**
136      * Was this request received on a secure connection?
137      */
138     protected boolean secure = false;
139 
140 
141     /**
142      * The server name associated with this Request.
143      */
144     protected String serverName = null;
145 
146 
147     /**
148      * The server port associated with this Request.
149      */
150     protected int serverPort = -1;
151 
152 
153     /**
154      * The ServletInputStream that has been returned by
155      * <code>getInputStream()</code>, if any.
156      */
157     protected ServletInputStream stream = null;
158 
159 
160     /**
161      * The ServletContext which is used to dispatch further requests
162      */
163     protected ServletContext servletContext;
164 
165     
166     
167     public ServletRequestImpl(ServletContext servletContext) {
168         this.servletContext = servletContext;
169     }
170     
171     // ------------------------------------------------------------- Properties
172 
173 
174 
175     /**
176      * Return the input stream associated with this Request.
177      */
178     public InputStream getStream() {
179 
180         return (this.input);
181 
182     }
183 
184 
185     /**
186      * Set the input stream associated with this Request.
187      *
188      * @param input The new input stream
189      */
190     public void setStream(InputStream input) {
191 
192         this.input = input;
193 
194     }
195 
196 
197 
198     // --------------------------------------------------------- Public Methods
199 
200 
201     /**
202      * Add a Locale to the set of preferred Locales for this Request.  The
203      * first added Locale will be the first one returned by getLocales().
204      *
205      * @param locale The new preferred Locale
206      */
207     public void addLocale(Locale locale) {
208 
209         synchronized (locales) {
210             locales.add(locale);
211         }
212 
213     }
214 
215 
216     /**
217      * Create and return a ServletInputStream to read the content
218      * associated with this Request.  The default implementation creates an
219      * instance of RequestStream associated with this request, but this can
220      * be overridden if necessary.
221      *
222      * @exception IOException if an input/output error occurs
223      */
224     public ServletInputStream createInputStream() throws IOException {
225 
226         //return (new RequestStream(this));
227         return null;
228 
229     }
230 
231 
232     /**
233      * Perform whatever actions are required to flush and close the input
234      * stream or reader, in a single operation.
235      *
236      * @exception IOException if an input/output error occurs
237      */
238     public void finishRequest() throws IOException {
239 
240         // If a Reader has been acquired, close it
241         if (reader != null) {
242             try {
243                 reader.close();
244             } catch (IOException e) {
245                 ;
246             }
247         }
248 
249         // If a ServletInputStream has been acquired, close it
250         if (stream != null) {
251             try {
252                 stream.close();
253             } catch (IOException e) {
254                 ;
255             }
256         }
257 
258         // The underlying input stream (perhaps from a socket)
259         // is not our responsibility
260 
261     }
262 
263 
264     /**
265      * Set the content length associated with this Request.
266      *
267      * @param length The new content length
268      */
269     public void setContentLength(int length) {
270 
271         this.contentLength = length;
272 
273     }
274 
275 
276     /**
277      * Set the content type (and optionally the character encoding)
278      * associated with this Request.  For example,
279      * <code>text/html; charset=ISO-8859-4</code>.
280      *
281      * @param type The new content type
282      */
283     public void setContentType(String type) {
284 
285         this.contentType = type;
286         if (type.indexOf(';') >= 0) {
287             //characterEncoding = RequestUtil.parseCharacterEncoding(type);
288         }
289 
290     }
291 
292 
293 
294     /**
295      * Set the protocol name and version associated with this Request.
296      *
297      * @param protocol Protocol name and version
298      */
299     public void setProtocol(String protocol) {
300 
301         this.protocol = protocol;
302 
303     }
304 
305 
306     /**
307      * Set the IP address of the remote client associated with this Request.
308      *
309      * @param remoteAddr The remote IP address
310      */
311     public void setRemoteAddr(String remoteAddr) {
312 
313         this.remoteAddr = remoteAddr;
314 
315     }
316 
317 
318     /**
319      * Set the fully qualified name of the remote client associated with this
320      * Request.
321      *
322      * @param remoteHost The remote host name
323      */
324     public void setRemoteHost(String remoteHost) {
325 
326         this.remoteHost = remoteHost;
327 
328     }
329 
330 
331     /**
332      * Set the name of the scheme associated with this request.  Typical values
333      * are <code>http</code>, <code>https</code>, and <code>ftp</code>.
334      *
335      * @param scheme The scheme
336      */
337     public void setScheme(String scheme) {
338 
339         this.scheme = scheme;
340 
341     }
342 
343 
344     /**
345      * Set the value to be returned by <code>isSecure()</code>
346      * for this Request.
347      *
348      * @param secure The new isSecure value
349      */
350     public void setSecure(boolean secure) {
351 
352         this.secure = secure;
353 
354     }
355 
356 
357     /**
358      * Set the name of the server (virtual host) to process this request.
359      *
360      * @param name The server name
361      */
362     public void setServerName(String name) {
363 
364         this.serverName = name;
365 
366     }
367 
368 
369     /**
370      * Set the port number of the server to process this request.
371      *
372      * @param port The server port
373      */
374     public void setServerPort(int port) {
375 
376         this.serverPort = port;
377 
378     }
379 
380 
381     // ------------------------------------------------- ServletRequest Methods
382 
383 
384     /**
385      * Return the specified request attribute if it exists; otherwise, return
386      * <code>null</code>.
387      *
388      * @param name Name of the request attribute to return
389      */
390     public Object getAttribute(String name) {
391 
392         synchronized (attributes) {
393             return (attributes.get(name));
394         }
395 
396     }
397 
398 
399     /**
400      * Return the names of all request attributes for this Request, or an
401      * empty <code>Enumeration</code> if there are none.
402      */
403     public Enumeration getAttributeNames() {
404 
405         synchronized (attributes) {
406             return new IteratorEnumeration(attributes.keySet().iterator());
407         }
408 
409     }
410 
411 
412     /**
413      * Return the character encoding for this Request.
414      */
415     public String getCharacterEncoding() {
416 
417         if (characterEncoding== null) {
418             characterEncoding= "ISO-8859-1";
419         }
420         return (this.characterEncoding);
421     }
422 
423 
424     /**
425      * Return the content length for this Request.
426      */
427     public int getContentLength() {
428 
429         return (this.contentLength);
430 
431     }
432 
433 
434     /**
435      * Return the content type for this Request.
436      */
437     public String getContentType() {
438 
439         return (contentType);
440 
441     }
442 
443 
444     /**
445      * Return the servlet input stream for this Request.  The default
446      * implementation returns a servlet input stream created by
447      * <code>createInputStream()</code>.
448      *
449      * @exception IllegalStateException if <code>getReader()</code> has
450      *  already been called for this request
451      * @exception IOException if an input/output error occurs
452      */
453     public ServletInputStream getInputStream() throws IOException {
454 
455         if (reader != null) {
456             throw new IllegalStateException( "getReader() has already been called" );
457         }
458 
459         if (stream == null)
460             stream = createInputStream();
461         return (stream);
462 
463     }
464 
465 
466     /**
467      * Return the preferred Locale that the client will accept content in,
468      * based on the value for the first <code>Accept-Language</code> header
469      * that was encountered.  If the request did not specify a preferred
470      * language, the server's default Locale is returned.
471      */
472     public Locale getLocale() {
473 
474         synchronized (locales) {
475             if (locales.size() > 0)
476                 return ((Locale) locales.get(0));
477             else
478                 return (defaultLocale);
479         }
480 
481     }
482 
483 
484     /**
485      * Return the set of preferred Locales that the client will accept
486      * content in, based on the values for any <code>Accept-Language</code>
487      * headers that were encountered.  If the request did not specify a
488      * preferred language, the server's default Locale is returned.
489      */
490     public Enumeration getLocales() {
491 
492         synchronized (locales) {
493             if (locales.size() > 0) {
494                 return new IteratorEnumeration( locales.iterator() );
495             }
496         }
497         return new IteratorEnumeration( new SingletonIterator( defaultLocale ) );
498 
499     }
500 
501 
502     /**
503      * Return the value of the specified request parameter, if any; otherwise,
504      * return <code>null</code>.  If there is more than one value defined,
505      * return only the first one.
506      *
507      * @param name Name of the desired request parameter
508      */
509     public String getParameter(String name) {
510         String values[] = (String[]) getParameterMap().get(name);
511         if (values != null)
512             return (values[0]);
513         else
514             return (null);
515 
516     }
517 
518 
519     /**
520      * Return the defined values for the specified request parameter, if any;
521      * otherwise, return <code>null</code>.
522      *
523      * @param name Name of the desired request parameter
524      */
525     public String[] getParameterValues(String name) {
526         String values[] = (String[]) getParameterMap().get(name);
527         if (values != null)
528             return (values);
529         else
530             return (null);
531     }
532     
533 
534     /**
535      * Returns a <code>Map</code> of the parameters of this request.
536      * Request parameters are extra information sent with the request.
537      * For HTTP servlets, parameters are contained in the query string
538      * or posted form data.
539      *
540      * @return A <code>Map</code> containing parameter names as keys
541      *  and parameter values as map values.
542      */
543     public Map getParameterMap() {
544         return new HashMap();
545     }
546 
547 
548     /**
549      * Return the names of all defined request parameters for this request.
550      */
551     public Enumeration getParameterNames() {
552         return new IteratorEnumeration(getParameterMap().keySet().iterator());
553     }
554     
555 
556     /**
557      * Return the protocol and version used to make this Request.
558      */
559     public String getProtocol() {
560 
561         return (this.protocol);
562 
563     }
564 
565 
566     /**
567      * Read the Reader wrapping the input stream for this Request.  The
568      * default implementation wraps a <code>BufferedReader</code> around the
569      * servlet input stream returned by <code>createInputStream()</code>.
570      *
571      * @exception IllegalStateException if <code>getInputStream()</code>
572      *  has already been called for this request
573      * @exception IOException if an input/output error occurs
574      */
575     public BufferedReader getReader() throws IOException {
576 
577         if (stream != null) {
578             throw new IllegalStateException( "getInputStream() has already been called" );
579         }
580 
581         if (reader == null) {
582             String encoding = getCharacterEncoding();
583             InputStreamReader isr =
584                 new InputStreamReader(createInputStream(), encoding);
585             reader = new BufferedReader(isr);
586         }
587         return (reader);
588 
589     }
590 
591 
592     /**
593      * Return the real path of the specified virtual path.
594      *
595      * @param path Path to be translated
596      *
597      * @deprecated As of version 2.1 of the Java Servlet API, use
598      *  <code>ServletContext.getRealPath()</code>.
599      */
600     public String getRealPath(String path) {
601 
602         if (servletContext == null)
603             return (null);
604         else {
605             try {
606                 return (servletContext.getRealPath(path));
607             } catch (IllegalArgumentException e) {
608                 return (null);
609             }
610         }
611 
612     }
613 
614 
615     /**
616      * Return the remote IP address making this Request.
617      */
618     public String getRemoteAddr() {
619 
620         return (this.remoteAddr);
621 
622     }
623 
624 
625     /**
626      * Return the remote host name making this Request.
627      */
628     public String getRemoteHost() {
629 
630         return (this.remoteHost);
631 
632     }
633 
634 
635     /**
636      * Return a RequestDispatcher that wraps the resource at the specified
637      * path, which may be interpreted as relative to the current request path.
638      *
639      * @param path Path of the resource to be wrapped
640      */
641     public RequestDispatcher getRequestDispatcher(String path) {
642         return servletContext.getRequestDispatcher(path);
643     }
644 
645 
646     /**
647      * Return the scheme used to make this Request.
648      */
649     public String getScheme() {
650 
651         return (this.scheme);
652 
653     }
654 
655 
656     /**
657      * Return the server name responding to this Request.
658      */
659     public String getServerName() {
660 
661         return (this.serverName);
662 
663     }
664 
665 
666     /**
667      * Return the server port responding to this Request.
668      */
669     public int getServerPort() {
670 
671         return (this.serverPort);
672 
673     }
674 
675 
676     /**
677      * Was this request received on a secure connection?
678      */
679     public boolean isSecure() {
680 
681         return (this.secure);
682 
683     }
684 
685 
686     /**
687      * Remove the specified request attribute if it exists.
688      *
689      * @param name Name of the request attribute to remove
690      */
691     public void removeAttribute(String name) {
692 
693         synchronized (attributes) {
694             attributes.remove(name);
695         }
696 
697     }
698 
699 
700     /**
701      * Set the specified request attribute to the specified value.
702      *
703      * @param name Name of the request attribute to set
704      * @param value The associated value
705      */
706     public void setAttribute(String name, Object value) {
707 
708         // Name cannot be null
709         if (name == null) {
710             throw new IllegalArgumentException( "Attribute name cannot be null" );
711         }
712 
713         // Null value is the same as removeAttribute()
714         if (value == null) {
715             removeAttribute(name);
716             return;
717         }
718 
719         synchronized (attributes) {
720             attributes.put(name, value);
721         }
722 
723     }
724 
725 
726     /**
727      * Overrides the name of the character encoding used in the body of
728      * this request.  This method must be called prior to reading request
729      * parameters or reading input using <code>getReader()</code>.
730      *
731      * @param enc The character encoding to be used
732      *
733      * @exception UnsupportedEncodingException if the specified encoding
734      *  is not supported
735      *
736      * @since Servlet 2.3
737      */
738     public void setCharacterEncoding(String enc)
739         throws UnsupportedEncodingException {
740 
741         // Ensure that the specified encoding is valid
742         byte buffer[] = new byte[1];
743         buffer[0] = (byte) 'a';
744         String dummy = new String(buffer, enc);
745 
746         // Save the validated encoding
747         this.characterEncoding = enc;
748     }
749 
750     /**
751      * Log a message to the current ServletContext
752      *
753      * @param message Message to be logged
754      */
755     protected void log(String message) {
756 
757         servletContext.log(message);
758 
759     }
760 
761 
762     /**
763      * Log a message to the current ServletContext
764      *
765      * @param message Message to be logged
766      * @param throwable Associated exception
767      */
768     protected void log(String message, Throwable throwable) {
769 
770         servletContext.log(message, throwable);
771 
772     }
773 
774 }