jdk/src/share/sample/nio/server/Request.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2004 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  *
       
     8  *   - Redistributions of source code must retain the above copyright
       
     9  *     notice, this list of conditions and the following disclaimer.
       
    10  *
       
    11  *   - Redistributions in binary form must reproduce the above copyright
       
    12  *     notice, this list of conditions and the following disclaimer in the
       
    13  *     documentation and/or other materials provided with the distribution.
       
    14  *
       
    15  *   - Neither the name of Sun Microsystems nor the names of its
       
    16  *     contributors may be used to endorse or promote products derived
       
    17  *     from this software without specific prior written permission.
       
    18  *
       
    19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
       
    20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
       
    21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
       
    23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
       
    27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
       
    28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
       
    29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    30  */
       
    31 
       
    32 import java.net.*;
       
    33 import java.nio.*;
       
    34 import java.nio.charset.*;
       
    35 import java.util.regex.*;
       
    36 
       
    37 /**
       
    38  * An encapsulation of the request received.
       
    39  * <P>
       
    40  * The static method parse() is responsible for creating this
       
    41  * object.
       
    42  *
       
    43  * @author Mark Reinhold
       
    44  * @author Brad R. Wetmore
       
    45  */
       
    46 class Request {
       
    47 
       
    48     /**
       
    49      * A helper class for parsing HTTP command actions.
       
    50      */
       
    51     static class Action {
       
    52 
       
    53         private String name;
       
    54         private Action(String name) { this.name = name; }
       
    55         public String toString() { return name; }
       
    56 
       
    57         static Action GET = new Action("GET");
       
    58         static Action PUT = new Action("PUT");
       
    59         static Action POST = new Action("POST");
       
    60         static Action HEAD = new Action("HEAD");
       
    61 
       
    62         static Action parse(String s) {
       
    63             if (s.equals("GET"))
       
    64                 return GET;
       
    65             if (s.equals("PUT"))
       
    66                 return PUT;
       
    67             if (s.equals("POST"))
       
    68                 return POST;
       
    69             if (s.equals("HEAD"))
       
    70                 return HEAD;
       
    71             throw new IllegalArgumentException(s);
       
    72         }
       
    73     }
       
    74 
       
    75     private Action action;
       
    76     private String version;
       
    77     private URI uri;
       
    78 
       
    79     Action action() { return action; }
       
    80     String version() { return version; }
       
    81     URI uri() { return uri; }
       
    82 
       
    83     private Request(Action a, String v, URI u) {
       
    84         action = a;
       
    85         version = v;
       
    86         uri = u;
       
    87     }
       
    88 
       
    89     public String toString() {
       
    90         return (action + " " + version + " " + uri);
       
    91     }
       
    92 
       
    93     static boolean isComplete(ByteBuffer bb) {
       
    94         int p = bb.position() - 4;
       
    95         if (p < 0)
       
    96             return false;
       
    97         return (((bb.get(p + 0) == '\r') &&
       
    98                  (bb.get(p + 1) == '\n') &&
       
    99                  (bb.get(p + 2) == '\r') &&
       
   100                  (bb.get(p + 3) == '\n')));
       
   101     }
       
   102 
       
   103     private static Charset ascii = Charset.forName("US-ASCII");
       
   104 
       
   105     /*
       
   106      * The expected message format is first compiled into a pattern,
       
   107      * and is then compared against the inbound character buffer to
       
   108      * determine if there is a match.  This convienently tokenizes
       
   109      * our request into usable pieces.
       
   110      *
       
   111      * This uses Matcher "expression capture groups" to tokenize
       
   112      * requests like:
       
   113      *
       
   114      *     GET /dir/file HTTP/1.1
       
   115      *     Host: hostname
       
   116      *
       
   117      * into:
       
   118      *
       
   119      *     group[1] = "GET"
       
   120      *     group[2] = "/dir/file"
       
   121      *     group[3] = "1.1"
       
   122      *     group[4] = "hostname"
       
   123      *
       
   124      * The text in between the parens are used to captured the regexp text.
       
   125      */
       
   126     private static Pattern requestPattern
       
   127         = Pattern.compile("\\A([A-Z]+) +([^ ]+) +HTTP/([0-9\\.]+)$"
       
   128                           + ".*^Host: ([^ ]+)$.*\r\n\r\n\\z",
       
   129                           Pattern.MULTILINE | Pattern.DOTALL);
       
   130 
       
   131     static Request parse(ByteBuffer bb) throws MalformedRequestException {
       
   132 
       
   133         CharBuffer cb = ascii.decode(bb);
       
   134         Matcher m = requestPattern.matcher(cb);
       
   135         if (!m.matches())
       
   136             throw new MalformedRequestException();
       
   137         Action a;
       
   138         try {
       
   139             a = Action.parse(m.group(1));
       
   140         } catch (IllegalArgumentException x) {
       
   141             throw new MalformedRequestException();
       
   142         }
       
   143         URI u;
       
   144         try {
       
   145             u = new URI("http://"
       
   146                         + m.group(4)
       
   147                         + m.group(2));
       
   148         } catch (URISyntaxException x) {
       
   149             throw new MalformedRequestException();
       
   150         }
       
   151         return new Request(a, m.group(3), u);
       
   152     }
       
   153 }