home *** CD-ROM | disk | FTP | other *** search
/ Java Developer's Companion / Java Developer's Companion.iso / binaries / Windows / jsdk / src / javax / servlet / http / HttpUtils.java < prev   
Encoding:
Java Source  |  1997-07-18  |  5.9 KB  |  201 lines

  1. /*
  2.  * @(#)HttpUtils.java    1.12 97/05/22
  3.  * 
  4.  * Copyright (c) 1995-1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion 1.0
  20.  */
  21.  
  22. package javax.servlet.http;
  23.  
  24. import javax.servlet.ServletInputStream;
  25. import java.util.Hashtable;
  26. import java.util.StringTokenizer;
  27. import java.io.IOException;
  28.  
  29. /**
  30.  * A collection of static utility methods useful to HTTP servlets.
  31.  *
  32.  * @version 1.12
  33.  */
  34. public class HttpUtils {
  35.  
  36.     static Hashtable nullHashtable = new Hashtable();
  37.  
  38.     /**
  39.      * Parses a query string and builds a hashtable of key, value pairs.
  40.      * The query string should have the form of a string packaged by the
  41.      * GET or POST method.  (For example, it should have its key, value
  42.      * pairs delimited by ampersands (&) and its keys separated from its
  43.      * values by equal signs (=).)  Keys can appear multiple times in the
  44.      * query string.  If a key does appear more than once, its values are
  45.      * stored in the hashtable as an array of strings.
  46.      * 
  47.      * <p> When the keys and values are moved into the hashtable, any
  48.      * plus signs (+) are returned to spaces and characters sent in
  49.      * hexadecimal notation (%xx) are converted back to characters.
  50.      * 
  51.      * @param s query string to be parsed
  52.      * @return a hashtable of the parsed key, value pairs.
  53.      * @exception IllegalArgumentException if the query string is invalid.
  54.      */
  55.     static public Hashtable parseQueryString(String s) {
  56.  
  57.     String valArray[] = null;
  58.     
  59.     if (s == null) {
  60.         throw new IllegalArgumentException();
  61.     }
  62.     Hashtable ht = new Hashtable();
  63.     StringBuffer sb = new StringBuffer();
  64.     StringTokenizer st = new StringTokenizer(s, "&");
  65.     while (st.hasMoreTokens()) {
  66.         String pair = (String)st.nextToken();
  67.         int pos = pair.indexOf('=');
  68.         if (pos == -1) {
  69.         throw new IllegalArgumentException();
  70.         }
  71.         String key = parseName(pair.substring(0, pos), sb);
  72.         String val = parseName(pair.substring(pos+1, pair.length()), sb);
  73.         if (ht.containsKey(key)) {
  74.         String oldVals[] = (String []) ht.get(key);
  75.         valArray = new String[oldVals.length + 1];
  76.         for (int i = 0; i < oldVals.length; i++) 
  77.             valArray[i] = oldVals[i];
  78.         valArray[oldVals.length] = val;
  79.         } else {
  80.         valArray = new String[1];
  81.         valArray[0] = val;
  82.         }
  83.         ht.put(key, valArray);
  84.     }
  85.     return ht;
  86.     }
  87.  
  88.     /**
  89.      * 
  90.      * Parses FORM data that is posted to the server using the HTTP
  91.      * POST method and the application/x-www-form-urlencoded mime
  92.      * type.
  93.      *
  94.      * @param len the length of the data in the input stream.
  95.      * @param in the input stream
  96.      * @return a hashtable of the parsed key, value pairs.  Keys
  97.      * with multiple values have their values stored as an array of strings
  98.      * @exception IllegalArgumentException if the POST data is invalid.
  99.      */
  100.     static public Hashtable parsePostData(int len, 
  101.                       ServletInputStream in) {
  102.  
  103.     int    inputLen, offset;
  104.     byte[] postedBytes = null;
  105.     String postedBody;
  106.  
  107.     if (len <=0)
  108.         return null;
  109.  
  110.     try {
  111.         //
  112.         // Make sure we read the entire POSTed body.
  113.         //
  114.         postedBytes = new byte [len];
  115.         offset = 0;
  116.         do {
  117.         inputLen = in.read (postedBytes, offset, len - offset);
  118.         if (inputLen <= 0)
  119.             throw new IOException ("short read");
  120.         offset += inputLen;
  121.         } while ((len - offset) > 0);
  122.  
  123.     } catch (IOException e) {
  124.         return nullHashtable;
  125.     }
  126.  
  127.     //
  128.     // XXX we shouldn't assume that the only kind of POST body
  129.     // is FORM data encoded using ASCII or ISO Latin/1 ... or
  130.     // that the body should always be treated as FORM data.
  131.     //
  132.     postedBody = new String (postedBytes, 0, 0, len);
  133.  
  134.     return parseQueryString(postedBody); 
  135.     }
  136.  
  137.  
  138.  
  139.  
  140.     /*
  141.      * Parse a name in the query string.
  142.      */
  143.     static private String parseName(String s, StringBuffer sb) {
  144.     sb.setLength(0);
  145.     for (int i = 0; i < s.length(); i++) {
  146.         char c = s.charAt(i);
  147.         switch (c) {
  148.           case '+':
  149.         sb.append(' ');
  150.         break;
  151.           case '%':
  152.         try {
  153.             sb.append((char) Integer.parseInt(s.substring(i+1, i+3), 
  154.                         16));
  155.         } catch (NumberFormatException e) {
  156.             throw new IllegalArgumentException();
  157.         }
  158.         i += 2;
  159.         break;
  160.           default:
  161.         sb.append(c);
  162.         break;
  163.         }
  164.     }
  165.     return sb.toString();
  166.     }
  167.  
  168.     /**
  169.      * Reconstructs the URL used by the client used to make the
  170.      * request.  This accounts for differences such as addressing
  171.      * scheme (http, https) and default ports, but does not attempt to
  172.      * include query parameters.  Since it returns a StringBuffer, not
  173.      * a String, the URL can be modified efficiently (for example, by
  174.      * appending query parameters).
  175.      *
  176.      * <P> This method is useful for creating redirect messages and for
  177.      * reporting errors.  */
  178.     public static StringBuffer getRequestURL (HttpServletRequest req) {
  179.     StringBuffer    url = new StringBuffer ();
  180.     String        scheme = req.getScheme ();
  181.     int        port = req.getServerPort ();
  182.  
  183.     String        servletPath = req.getServletPath ();
  184.     String        pathInfo = req.getPathInfo ();
  185.  
  186.     url.append (scheme);        // http, https
  187.     url.append ("://");
  188.     url.append (req.getServerName ());
  189.     if ((scheme.equals ("http") && port != 80)
  190.         || (scheme.equals ("https") && port != 443)) {
  191.         url.append (':');
  192.         url.append (req.getServerPort ());
  193.     }
  194.     if (servletPath != null)
  195.         url.append (servletPath);
  196.     if (pathInfo != null)
  197.         url.append (pathInfo);
  198.     return url;
  199.     }
  200. }
  201.