Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/tripi/asp/Request.java


1   /**
2    * ArrowHead ASP Server 
3    * This is a source file for the ArrowHead ASP Server - an 100% Java
4    * VBScript interpreter and ASP server.
5    *
6    * For more information, see http://www.tripi.com/arrowhead
7    *
8    * Copyright (C) 2002  Terence Haddock
9    *
10   * This program is free software; you can redistribute it and/or modify
11   * it under the terms of the GNU General Public License as published by
12   * the Free Software Foundation; either version 2 of the License, or
13   * (at your option) any later version.
14   *
15   * This program is distributed in the hope that it will be useful,
16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   * GNU General Public License for more details.
19   *
20   * You should have received a copy of the GNU General Public License
21   * along with this program; if not, write to the Free Software
22   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23   *
24   */
25  package com.tripi.asp;
26  
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.io.Reader;
30  import java.util.Enumeration;
31  import java.util.Hashtable;
32  import java.util.Iterator;
33  import java.util.Map;
34  
35  import javax.servlet.http.Cookie;
36  import javax.servlet.http.HttpServletRequest;
37  
38  import org.apache.log4j.Category;
39  
40  import com.tripi.asp.util.ParseQueryString;
41  import com.tripi.asp.util.Tools;
42  
43  /**
44   * Request is a class which holds request-specific data.
45   * It is an adaptor class which allows access to the Java Servlet
46   * javax.servlet.http.HttpServletRequest class.
47   * Implementation state:
48   * <ul>
49   * <li><b>Cookies</b> - Implemented. <b>Note</b> does not support cookies
50   * like "VALUE=First&amp;VALUE=Second", does support cookies like
51   * "VALUE1=First&amp;VALUE2=Second".
52   * <li><b>Form</b> - Fully implemented.
53   * <li><b>QueryString</b> - Fully implemented.
54   * <li><b>ServerVariables</b> - Fully implemented.
55   * <li><b>TotalBytes</b> - Fully implemented.
56   * <li><b>BinaryRead</b> - Fully implemented.
57   * </ul>
58   * 
59   * @author Terence Haddock
60   * @version 0.9
61   */
62  public class Request implements SimpleMap
63  {
64      /** Debugging category */
65      static private Category DBG = Category.getInstance(Request.class);
66  
67      /** Java servlet request object */
68      HttpServletRequest request;
69  
70      /** QueryString sub-object */
71      public QueryStringObj QueryString;
72  
73      /** ServerVariables sub-object */
74      public ServerVariablesObj ServerVariables;
75  
76      /** Form sub-object */
77      public FormObj Form;
78  
79      /** Cookies sub-object */
80      public CookiesObj Cookies;
81  
82      /**
83       * Constructor.
84       * @param request Java servlet request object.
85       * @see HttpServletRequest
86       */
87      public Request(HttpServletRequest request) throws AspException
88      {
89          this.request = request;
90          try {
91              request.setCharacterEncoding("UTF-8");
92          } catch (java.io.UnsupportedEncodingException ex)
93          {
94              throw new AspNestedException(ex);
95          }
96          QueryString = new QueryStringObj(request.getQueryString());
97          ServerVariables = new ServerVariablesObj(request);
98          Form = new FormObj(request);
99          Cookies = new CookiesObj(request);
100     }
101 
102     /**
103      * This unsupported ASP-accessible function obtains the 
104      * HttpServletRequest object that this Request object points to.
105      * @return HttpServletRequest object
106      */
107     public HttpServletRequest getHttpServletRequest()
108     {
109         return request;
110     }
111 
112     /**
113      * SimpleMap interface, obtains the value of an object stored in one
114      * of the sub objects, in the following order: QueryString, Form, Cookies,
115      * ServerVariables.
116      * @param obj Key of object to obtain. Will be coerced to string and
117      * is case insensitive.
118      * @return value stored at the given position, or UndefinedValueNode
119      * if no value is found
120      * @throws AspException on error.
121      * @see SimpleMap#get(Object)
122      */
123     public Object get(Object obj) throws AspException
124     {
125         Object queryString = QueryString.get(obj);
126         if (!(queryString instanceof UndefinedValueNode)) {
127             return queryString;
128         }
129         Object formValue = Form.get(obj);
130         if (!(formValue instanceof UndefinedValueNode)) {
131             return formValue;
132         }
133         Object serverVariable = ServerVariables.get(obj);
134         if (!(serverVariable instanceof UndefinedValueNode)) {
135             return serverVariable;
136         }
137         return Constants.undefinedValueNode;
138     }
139 
140     /**
141      * Stores a value in this object. This method will always throw
142      * a AspReadOnlyException error.
143      * @param key Key to store this object under.
144      * @param value Value to store with the given key.
145      * @throws AspException always, throws AspReadOnlyException.
146      * @see SimpleMap#put(Object,Object)
147      */
148     public void put(Object key, Object value) throws AspException
149     {
150         throw new AspReadOnlyException("Request");
151     }
152 
153     /**
154      * Obtains the list of keys in this object. Not currently implemented.
155      * @return enumeration of keys in this object.
156      * @throws AspException always, throws AspNotImplementedException    
157      * @see SimpleMap#getKeys
158      */
159     public Enumeration getKeys() throws AspException
160     {
161         throw new AspNotImplementedException("getKeys");
162     }
163 
164     /**
165      * Obtain the content length of the request.
166      * @return content length of the request.
167      */
168     public int TotalBytes()
169     {
170         int totalBytes = request.getContentLength();
171         if (totalBytes == -1) return 0;
172         return totalBytes;
173     }
174 
175     /**
176      * Read the data from the form.
177      * @param length number of bytes to read
178      * @return array of data from the form.
179      */
180     public byte[] BinaryRead(int length) throws IOException
181     {
182         StringBuffer buf = new StringBuffer();
183         byte bytes[] = new byte[length];
184         InputStream is = request.getInputStream();
185 
186         int nread = 0;
187 
188         
189         if (DBG.isDebugEnabled()) DBG.debug("Length: " + length);
190         while (nread < length) {
191             int thistime = is.read(bytes, nread, length - nread);
192             if (DBG.isDebugEnabled()) {
193                 DBG.debug("nread: " + nread);
194                 DBG.debug("thistime: " + thistime);
195             }
196             if (thistime <= 0) break;
197             nread += thistime;
198         }
199         
200         if (DBG.isDebugEnabled()) DBG.debug("Total read: " + nread);
201         while (nread < length) {
202             byte nbytes[] = new byte[nread];
203             System.arraycopy(bytes, 0, nbytes, 0, nread);
204             bytes = nbytes;
205         }
206         return bytes;
207     }
208 
209     /**
210      * The ServerVariablesObj implemnets the Request.ServerVariables
211      * object, containing a list of server variables.
212      */
213     static public class ServerVariablesObj implements SimpleMap
214     {
215         /** Reference to the collection object */
216         public AspCollection Contents = new ServerVariablesContents();
217 
218         /** HTTP Servlet Request object */
219         HttpServletRequest req;
220 
221         /**
222          * Constructor.
223          * @param req HTTP Servlet Request object
224          */
225         ServerVariablesObj(HttpServletRequest req)
226         {
227             this.req = req;
228         }
229 
230         /**
231          * This class handles the Contents varable, which is not defined
232          * until it is first accessed.
233          */
234         class ServerVariablesContents extends AspCollection
235         {
236             /**
237              * Initialize the values for this collection
238              */
239             protected void initialize() throws AspException
240             {
241                 try {
242                     super.initialize();
243                     /* Fill the hashtable with the predefined server variable
244                        names. */
245                     String REQUEST_METHOD = req.getMethod();
246                     if (REQUEST_METHOD != null) 
247                         this.put("REQUEST_METHOD", REQUEST_METHOD);
248                     String URL = req.getRequestURI();
249                     if (URL != null)
250                         this.put("URL", URL);
251                     String SERVER_PROTOCOL = req.getProtocol();
252                     if (SERVER_PROTOCOL != null)
253                         this.put("SERVER_PROTOCOL", SERVER_PROTOCOL);
254                     String SCRIPT_NAME = req.getServletPath();
255                     if (SCRIPT_NAME != null)
256                         this.put("SCRIPT_NAME", SCRIPT_NAME);
257                     String PATH_INFO = req.getPathInfo();
258                     if (PATH_INFO != null)
259                         this.put("PATH_INFO", PATH_INFO);
260                     String PATH_TRANSLATED = req.getPathTranslated();
261                     if (PATH_TRANSLATED != null)
262                         this.put("PATH_TRANSLATED", PATH_TRANSLATED);
263                     String QUERY_STRING = req.getQueryString();
264                     if (QUERY_STRING != null)
265                         this.put("QUERY_STRING", QUERY_STRING);
266                     int ContentLength = req.getContentLength();
267                     if (ContentLength == -1) ContentLength = 0;
268                     Integer CONTENT_LENGTH = new Integer(ContentLength);
269                     this.put("CONTENT_LENGTH", CONTENT_LENGTH);
270                     String CONTENT_TYPE = req.getContentType();
271                     if (CONTENT_TYPE != null)
272                         this.put("CONTENT_TYPE", CONTENT_TYPE);
273                     String SERVER_NAME = req.getServerName();
274                     if (SERVER_NAME != null)
275                         this.put("SERVER_NAME", SERVER_NAME);
276                     this.put("SERVER_PORT",
277                         new Integer(req.getServerPort()));
278                     String REMOTE_USER = req.getRemoteUser();
279                     if (REMOTE_USER != null)
280                         this.put("REMOTE_USER", REMOTE_USER);
281                     String REMOTE_ADDR = req.getRemoteAddr();
282                     if (REMOTE_ADDR != null)
283                         this.put("REMOTE_ADDR", REMOTE_ADDR);
284                     String REMOTE_HOST = req.getRemoteHost();
285                     if (REMOTE_HOST != null)
286                         this.put("REMOTE_HOST", REMOTE_HOST);
287                     String AUTH_TYPE = req.getAuthType();
288                     if (AUTH_TYPE != null)
289                         this.put("AUTH_TYPE", AUTH_TYPE);
290                     /* Fill the hashtable with all of the included server headers,
291                        mangling the name (prepending with HTTP_ and converting
292                        -'s to _'s. */
293                     Enumeration enNames = req.getHeaderNames();
294                     while (enNames.hasMoreElements()) {
295                         String name = (String)enNames.nextElement();
296                         String value = req.getHeader(name);
297                         String newName = "HTTP_" + name.toUpperCase();
298                         newName = newName.replace('-', '_');
299                         this.put(newName, value);
300                     }
301                 } finally {
302                     setReadOnly();
303                 }
304             }
305         }
306 
307         /**
308          * Obtain the value of a server variable.
309          * @param obj Key to obtain, will be converted to string and is
310          * case insensitive.
311          * @return value of server variable with the specified key.
312          * @throws AspException on error
313          * @see SimpleMap#get(Object)
314          */
315         public Object get(Object obj) throws AspException
316         {
317             return Contents.get(obj);
318         }
319 
320         /**
321          * Stores a value with a specified key. ServerVariables are read-only    
322          * so this method always throws an AspReadOnlyException error.
323          * @param key Key to store value under.
324          * @param value Value to store.
325          * @throws AspException always, AspReadOnlyException
326          * @see SimpleMap#put
327          */
328         public void put(Object key, Object value) throws AspException
329         {
330             throw new AspReadOnlyException("Request.ServerVariables");
331         }
332 
333         /**
334          * Obtains the keys of objects stored in this object.
335          * @return Enumeration of keys stored in this object.
336          * @see SimpleMap#getKeys
337          */
338         public Enumeration getKeys() throws AspException
339         {
340             return Contents.keys();
341         }
342     }
343 
344     /**
345      * QueryStringObj implements the Request.QueryString object.
346      */
347     static public class QueryStringObj implements SimpleMap, SimpleReference
348     {
349         /** Collection reference to query string values */
350         public AspCollection Contents = new QueryStringContents();
351 
352         /** The entire query string */
353         String wholeString;
354 
355         /**    
356          * Constructor.
357          * @param queryString the entire query string.
358          */
359         public QueryStringObj(String queryString) {
360             this.wholeString = queryString;
361         }
362 
363         /**
364          * SimpleReference read method which obtains the full value of this string.
365          * @return full query string.
366          * @throws AspException on error.
367          * @see SimpleReference#getValue
368          */
369         public Object getValue() throws AspException
370         {
371             return wholeString;
372         }
373         
374         /**
375          * SimpleReference write method which always throws an
376          * AspReadOnlyException because Request.QueryString objects
377          * are read-only.
378          * @param obj New value for Request.QueryString
379          * @throws AspException always throws AspReadOnlyException
380          * @see SimpleReference#setValue
381          */
382         public void setValue(Object obj) throws AspException
383         {
384             throw new AspReadOnlyException("Request.QueryString");
385         }
386 
387         /**
388          * SimpleMap read method which obtains the value of a specific
389          * parameter in the query string.
390          * @param obj Name of object to obtain, will be converted to
391          * string and is case insensitive.
392          * @return value of query string parameter given by obj key, this
393          * value will actually be an instance of the QueryStringValue class in
394          * order to implement methods and arrays of query string values.
395          * @throws AspException on error.
396          * @see SimpleReference#get
397          */
398         public Object get(Object obj) throws AspException
399         {
400             return Contents.get(obj);
401         }
402 
403         /**
404          * SimpleMap write method which stores a value with the specified
405          * key. This method always throws AspReadOnlyException since
406          * Request.QueryString is read-only.
407          * @param key Key of object to store
408          * @param value object to store.
409          * @throws AspException always throws AspReadOnlyException
410          * @see SimpleMap#put
411          */
412         public void put(Object key, Object value) throws AspException
413         {
414             throw new AspReadOnlyException("Request.QueryString");
415         }
416 
417         /**
418          * Obtains the names of parameters stored in this object.
419          * @return Enumeration of keys stored in this object.
420          * @see SimpleMap#getKeys
421          */
422         public Enumeration getKeys() throws AspException
423         {
424             return Contents.getKeys();
425         }
426 
427         /**
428          * ASP-Accessible function to obtain the number of items in this
429          * query string.
430          * @return number of items in this query string
431          */
432         public int Count() throws AspException
433         {
434             return Contents.Count();
435         }
436 
437         /**
438          * This class handles the Contents varable, which is not defined
439          * until it is first accessed.
440          */
441         class QueryStringContents extends AspCollection
442         {
443             /**
444              * Initialized the values for the query string contents
445              */
446             protected void initialize() throws AspException
447             {
448                 try {
449                     super.initialize();
450                     /* Parse out all of the param/value pairs */
451                     Map paramValues = Tools.parseQueryString(wholeString);
452                     Tools.convertToMultiValue(this, paramValues, true);
453                 } finally {
454                     setReadOnly();
455                 }
456             }
457         }
458     }
459 
460     /**
461      * The FormObj class implements the interface between ASP Request.Form
462      * object and the Servlet API. The form values are 'lazy' evaluated
463      * to keep from accessing the Servlet's input stream until required,
464      * in case the BinaryRead function will be called.
465      */
466     static public class FormObj implements SimpleMap
467     {
468         /** AspCollection to store form data */
469         public AspCollection Contents = new FormContents();
470 
471         /** Java Servlet request object */
472         HttpServletRequest request;
473 
474         /**
475          * Constructor.
476          * @param request Java Servlet request object.
477          */
478         FormObj(HttpServletRequest request)
479         {
480             this.request = request;
481         }
482 
483         /**
484          * Obtains the list of keys in this object.
485          * @return Enumeration of keys in this object.
486          * @throws AspException on error.
487          */
488         public Enumeration getKeys() throws AspException
489         {
490             return Contents.getKeys();
491         }
492 
493         /**
494          * Obtains a form value with the specified key.
495          * @param obj Key of form parameter, will be converted to string
496          * and is case insensitive.
497          * @return instance of FormValue class corresponding to the
498          * parameter name given.
499          * @throws AspException on error.
500          * @see SimpleMap#get
501          */
502         public Object get(Object obj) throws AspException
503         {
504             return Contents.get(obj);
505         }
506 
507         /**
508          * Implements the SimpleMap.put interface function. Will always
509          * throw a AspReadOnlyException becaues Request.Form is read-only.
510          * @param key Key of object to store.
511          * @param value Object to store
512          * @throws AspException on error
513          * @see SimpleMap#put
514          */
515         public void put(Object key, Object value) throws AspException
516         {
517             throw new AspReadOnlyException("Request.Form");
518         }
519 
520         /**
521          * ASP-Accessible function to obtain the number of items in this form.
522          * @return number of items in this form
523          */
524         public int Count() throws AspException
525         {
526             return Contents.Count();
527         }
528 
529         /**
530          * This class implements processing specific to a form
531          * data object.
532          */
533         class FormContents extends AspCollection
534         {
535             /**
536              * Empty mult-value
537              */
538             public Tools.MultiValue emptyValue = null;
539 
540             /**
541              * This internal function initialized the form contents.
542              */
543             protected void initialize() throws AspException
544             {
545                 super.initialize();
546 
547                 try {
548                     /* Check if this is a POST */
549                     if (!request.getMethod().equalsIgnoreCase("POST"))
550                     {
551                         return;
552                     }
553                     /* Check if this is an understood content type */
554                     if (!request.getContentType().
555                             equalsIgnoreCase("application/x-www-form-urlencoded")) {
556                         return;
557                     }
558                     int len = request.getContentLength();
559                     Reader in;
560                     Map htValues;
561                     try {
562                         in = request.getReader();
563                         htValues = ParseQueryString.parse(in, len);
564                     } catch (IOException ex) {
565                         throw new AspException("Input error: " + ex);
566                     }
567                     Tools.convertToMultiValue(this, htValues, false);
568     
569                     emptyValue = new Tools.MultiValue();
570                 } finally {
571                     setReadOnly();
572                 }
573             }
574 
575             /**
576              * Overriding the get function in order to handle empty items.
577              * @param key Key/Index to obtain
578              * @return value for the key/index
579              * @throws AspException in an error occurs
580              */
581             public synchronized Object get(Object key) throws AspException
582             {
583                 Object value = super.get(key);
584                 if (emptyValue != null && value instanceof UndefinedValueNode)
585                 {
586                     return emptyValue;
587                 }
588                 return value;
589             }
590         }
591     }
592 
593     /**
594      * The CookiesObj class implementes the interface between the ASP 
595      * Request.Cookies object and the Servlet API.
596      */
597     static public class CookiesObj implements SimpleMap
598     {
599         /** List of value of cookies */
600         Hashtable cookieValues = null;
601 
602         /** An "empty" value used for non-existant cookies */
603         CookieValue emptyCookie = new CookieValue();
604 
605         /** List of cookies in this request */
606         Cookie cookies[];
607 
608         /**
609          * Constructor.
610          * @param request Java Servlet request object.
611          */
612         CookiesObj(HttpServletRequest request)
613         {
614             this.cookies = request.getCookies();
615             /* Parse through the cookies and get their values */
616             cookieValues = new Hashtable();
617             if (cookies != null)
618             for (int i = 0; i < cookies.length; i++)
619             {
620                 Cookie cookie = cookies[i];
621                 CookieValue cookieValue = new CookieValue(cookie);
622                 if (DBG.isDebugEnabled()) {
623                     DBG.debug("Adding cookie: " + cookie);
624                 }
625                 cookieValues.put(new IdentNode(cookie.getName()), cookieValue);
626             }
627         }
628 
629         /**
630          * Obtains the list of keys in this object.
631          * @return Enumeration of keys in this object.
632          * @throws AspException on error.
633          */
634         public Enumeration getKeys() throws AspException
635         {
636             return cookieValues.keys();
637         }
638 
639         /**
640          * Obtains a cookie value with the specified key.
641          * @param obj Key of form parameter, will be converted to string
642          * and is case insensitive.
643          * @return instance of CookieValue class corresponding to the
644          * parameter name given.
645          * @throws AspException on error.
646          * @see SimpleMap#get
647          */
648         public Object get(Object obj) throws AspException
649         {
650             IdentNode strValue = new IdentNode(Types.coerceToString(obj));
651             if (!cookieValues.containsKey(strValue)) {
652                 return emptyCookie;
653             }
654             return cookieValues.get(strValue);
655         }
656 
657         /**
658          * Implements the SimpleMap.put interface function. Will always
659          * throw a AspReadOnlyException becaues Request.Form is read-only.
660          * @param key Key of object to store.
661          * @param value Object to store
662          * @throws AspException on error
663          * @see SimpleMap#put
664          */
665         public void put(Object key, Object value) throws AspException
666         {
667             throw new AspReadOnlyException("Request.Cookies");
668         }
669 
670         /**
671          * CookieValue class contains methods and functions related
672          * to the value of a cookie.
673          */
674         static class CookieValue implements SimpleReference, SimpleMap
675         {            
676             /** Hashtable of values in this cookie */
677             Hashtable cookieValues = new Hashtable();
678 
679             /** String containing the entire list of values */
680             String valuesAsString;
681 
682             /**
683              * Constructor. FormValue is initally created with no values.
684              */
685             CookieValue()
686             {
687                 valuesAsString = null;
688             }
689 
690             /**
691              * Constructor from a cookie object.
692              * @param cookie Cookie object
693              */
694             CookieValue(Cookie cookie)
695             {
696                 valuesAsString = cookie.getValue();
697                 /* XXX Not sure if this works */
698                 if (DBG.isDebugEnabled()) DBG.debug("Cookie values: " +
699                         valuesAsString);
700                 if (valuesAsString.indexOf('=') != -1) 
701                 {
702                     Map hashValues = ParseQueryString.parse(valuesAsString);
703                     /* Lowercase the value keys */
704                     for (Iterator i = hashValues.keySet().iterator(); i.hasNext();)
705                     {
706                         String key = (String)i.next();
707                         String value[] = (String[])hashValues.get(key);
708                         if (DBG.isDebugEnabled()) {
709                             DBG.debug("Key: " + key);
710                             DBG.debug("Value: " + value[0]);
711                         }
712                         cookieValues.put(new IdentNode(key), value[0]);
713                     }
714                 }
715             }
716 
717             /**
718              * Obtains a specific index in this array of values.
719              * @param value index to obtain, will be converted to an string.
720              * @return string value of form at the specified index.
721              * @throws AspException on error
722              * @see SimpleMap#get
723              */
724             public Object get(Object value) throws AspException
725             {
726                 IdentNode iValue = new IdentNode(Types.coerceToString(value));
727                 if (!cookieValues.containsKey(iValue)) {
728                     return Constants.undefinedValueNode;
729                 }
730                 Object res = cookieValues.get(iValue);
731                 if (DBG.isDebugEnabled())
732                     DBG.debug("Get key: " + res);
733                 return res;
734             }
735 
736             /**
737              * Stores a value. This method always returned an
738              * AspReadOnlyException because Request.Form values
739              * are read-only.
740              * @param key Key to store
741              * @param value Value to store.
742              * @throws AspException always throws AspReadOnlyException
743              */
744             public void put(Object key, Object value) throws AspException
745             {
746                 throw new AspReadOnlyException("Request.Cookies");
747             }
748 
749             /**
750              * Obtains the list of values in this Request.Form(x) array.
751              * @return enumeration of the list of values in this array.
752              * @throws AspException on error
753              */
754             public Enumeration getKeys() throws AspException
755             {
756                 return cookieValues.keys();
757             }
758 
759             /**
760              * Obtains the entire value array
761              * @return the entire value array
762              * @throws AspException on error
763              */
764             public Object getValue() throws AspException
765             {
766                 if (valuesAsString == null)
767                     return Constants.undefinedValueNode;
768                 return valuesAsString;
769             }
770 
771             /**
772              * Sets the value of this value array. Always throws 
773              * AspReadOnlyException because this array is read-only.
774              * @param obj Value to set.
775              * @throws AspException on error.
776              */
777             public void setValue(Object obj) throws AspException
778             {
779                 throw new AspException("Modification of read-only variable");
780             }
781 
782             /**
783              * Converts this value array to a string. For debugging only.
784              * @return string representation of this value array.
785              */
786             public String toString()
787             {
788                 return "{CookieValue(" + cookieValues + ")}";
789             }
790         }
791     }
792 }