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.charset.*;
     44 
     45 /**
     46  * An object used for sending Content to the requestor.
     47  *
     48  * @author Mark Reinhold
     49  * @author Brad R. Wetmore
     50  */
     51 class Reply implements Sendable {
     52 
     53     /**
     54      * A helper class which define the HTTP response codes
     55      */
     56     static class Code {
     57 
     58         private int number;
     59         private String reason;
     60         private Code(int i, String r) { number = i; reason = r; }
     61         public String toString() { return number + " " + reason; }
     62 
     63         static Code OK = new Code(200, "OK");
     64         static Code BAD_REQUEST = new Code(400, "Bad Request");
     65         static Code NOT_FOUND = new Code(404, "Not Found");
     66         static Code METHOD_NOT_ALLOWED = new Code(405, "Method Not Allowed");
     67 
     68     }
     69 
     70     private Code code;
     71     private Content content;
     72     private boolean headersOnly;
     73 
     74     Reply(Code rc, Content c) {
     75         this(rc, c, null);
     76     }
     77 
     78     Reply(Code rc, Content c, Request.Action head) {
     79         code = rc;
     80         content = c;
     81         headersOnly = (head == Request.Action.HEAD);
     82     }
     83 
     84     private static String CRLF = "\r\n";
     85     private static Charset ascii = Charset.forName("US-ASCII");
     86 
     87     private ByteBuffer hbb = null;
     88 
     89     private ByteBuffer headers() {
     90         CharBuffer cb = CharBuffer.allocate(1024);
     91         for (;;) {
     92             try {
     93                 cb.put("HTTP/1.0 ").put(code.toString()).put(CRLF);
     94                 cb.put("Server: niossl/0.1").put(CRLF);
     95                 cb.put("Content-type: ").put(content.type()).put(CRLF);
     96                 cb.put("Content-length: ")
     97                     .put(Long.toString(content.length())).put(CRLF);
     98                 cb.put(CRLF);
     99                 break;
    100             } catch (BufferOverflowException x) {
    101                 assert(cb.capacity() < (1 << 16));
    102                 cb = CharBuffer.allocate(cb.capacity() * 2);
    103                 continue;
    104             }
    105         }
    106         cb.flip();
    107         return ascii.encode(cb);
    108     }
    109 
    110     public void prepare() throws IOException {
    111         content.prepare();
    112         hbb = headers();
    113     }
    114 
    115     public boolean send(ChannelIO cio) throws IOException {
    116 
    117         if (hbb == null)
    118             throw new IllegalStateException();
    119 
    120         if (hbb.hasRemaining()) {
    121             if (cio.write(hbb) <= 0)
    122                 return true;
    123         }
    124 
    125         if (!headersOnly) {
    126             if (content.send(cio))
    127                 return true;
    128         }
    129 
    130         if (!cio.dataFlush())
    131             return true;
    132 
    133         return false;
    134     }
    135 
    136     public void release() throws IOException {
    137         content.release();
    138     }
    139 }
    140