Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright (c) 2004, 2011, Oracle and/or its affiliates. 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 Oracle 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 /*
     33  * This source code is provided to illustrate the usage of a given feature
     34  * or technique and has been deliberately simplified. Additional steps
     35  * required for a production-quality application, such as security checks,
     36  * input validation and proper error handling, might not be present in
     37  * this sample code.
     38  */
     39 
     40 
     41 import java.io.*;
     42 import java.nio.*;
     43 import java.nio.channels.*;
     44 
     45 /**
     46  * Primary driver class used by non-blocking Servers to receive,
     47  * prepare, send, and shutdown requests.
     48  *
     49  * @author Mark Reinhold
     50  * @author Brad R. Wetmore
     51  */
     52 class RequestHandler implements Handler {
     53 
     54     private ChannelIO cio;
     55     private ByteBuffer rbb = null;
     56 
     57     private boolean requestReceived = false;
     58     private Request request = null;
     59     private Reply reply = null;
     60 
     61     private static int created = 0;
     62 
     63     RequestHandler(ChannelIO cio) {
     64         this.cio = cio;
     65 
     66         // Simple heartbeat to let user know we're alive.
     67         synchronized (RequestHandler.class) {
     68             created++;
     69             if ((created % 50) == 0) {
     70                 System.out.println(".");
     71                 created = 0;
     72             } else {
     73                 System.out.print(".");
     74             }
     75         }
     76     }
     77 
     78     // Returns true when request is complete
     79     // May expand rbb if more room required
     80     //
     81     private boolean receive(SelectionKey sk) throws IOException {
     82         ByteBuffer tmp = null;
     83 
     84         if (requestReceived) {
     85             return true;
     86         }
     87 
     88         if (!cio.doHandshake(sk)) {
     89             return false;
     90         }
     91 
     92         if ((cio.read() < 0) || Request.isComplete(cio.getReadBuf())) {
     93             rbb = cio.getReadBuf();
     94             return (requestReceived = true);
     95         }
     96         return false;
     97     }
     98 
     99     // When parse is successfull, saves request and returns true
    100     //
    101     private boolean parse() throws IOException {
    102         try {
    103             request = Request.parse(rbb);
    104             return true;
    105         } catch (MalformedRequestException x) {
    106             reply = new Reply(Reply.Code.BAD_REQUEST,
    107                               new StringContent(x));
    108         }
    109         return false;
    110     }
    111 
    112     // Ensures that reply field is non-null
    113     //
    114     private void build() throws IOException {
    115         Request.Action action = request.action();
    116         if ((action != Request.Action.GET) &&
    117                 (action != Request.Action.HEAD)) {
    118             reply = new Reply(Reply.Code.METHOD_NOT_ALLOWED,
    119                               new StringContent(request.toString()));
    120         }
    121         reply = new Reply(Reply.Code.OK,
    122                           new FileContent(request.uri()), action);
    123     }
    124 
    125     public void handle(SelectionKey sk) throws IOException {
    126         try {
    127 
    128             if (request == null) {
    129                 if (!receive(sk))
    130                     return;
    131                 rbb.flip();
    132                 if (parse())
    133                     build();
    134                 try {
    135                     reply.prepare();
    136                 } catch (IOException x) {
    137                     reply.release();
    138                     reply = new Reply(Reply.Code.NOT_FOUND,
    139                                       new StringContent(x));
    140                     reply.prepare();
    141                 }
    142                 if (send()) {
    143                     // More bytes remain to be written
    144                     sk.interestOps(SelectionKey.OP_WRITE);
    145                 } else {
    146                     // Reply completely written; we're done
    147                     if (cio.shutdown()) {
    148                         cio.close();
    149                         reply.release();
    150                     }
    151                 }
    152             } else {
    153                 if (!send()) {  // Should be rp.send()
    154                     if (cio.shutdown()) {
    155                         cio.close();
    156                         reply.release();
    157                     }
    158                 }
    159             }
    160         } catch (IOException x) {
    161             String m = x.getMessage();
    162             if (!m.equals("Broken pipe") &&
    163                     !m.equals("Connection reset by peer")) {
    164                 System.err.println("RequestHandler: " + x.toString());
    165             }
    166 
    167             try {
    168                 /*
    169                  * We had a failure here, so we'll try to be nice
    170                  * before closing down and send off a close_notify,
    171                  * but if we can't get the message off with one try,
    172                  * we'll just shutdown.
    173                  */
    174                 cio.shutdown();
    175             } catch (IOException e) {
    176                 // ignore
    177             }
    178 
    179             cio.close();
    180             if (reply !=  null) {
    181                 reply.release();
    182             }
    183         }
    184 
    185     }
    186 
    187     private boolean send() throws IOException {
    188         try {
    189             return reply.send(cio);
    190         } catch (IOException x) {
    191             if (x.getMessage().startsWith("Resource temporarily")) {
    192                 System.err.println("## RTA");
    193                 return true;
    194             }
    195             throw x;
    196         }
    197     }
    198 }
    199