• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RequestHandler(ChannelIO cio)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     //
receive(SelectionKey sk)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     //
parse()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     //
build()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 
handle(SelectionKey sk)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 
send()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