Source Code Cross Referenced for HttpListener.java in  » Web-Server » Winstone » winstone » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Winstone » winstone 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
003:         * Distributed under the terms of either:
004:         * - the common development and distribution license (CDDL), v1.0; or
005:         * - the GNU Lesser General Public License, v2.1 or later
006:         */
007:        package winstone;
008:
009:        import java.io.IOException;
010:        import java.io.InputStream;
011:        import java.io.InterruptedIOException;
012:        import java.io.OutputStream;
013:        import java.net.InetAddress;
014:        import java.net.ServerSocket;
015:        import java.net.Socket;
016:        import java.net.SocketException;
017:        import java.util.ArrayList;
018:        import java.util.List;
019:        import java.util.Map;
020:
021:        /**
022:         * Implements the main listener daemon thread. This is the class that gets
023:         * launched by the command line, and owns the server socket, etc. Note that this
024:         * class is also used as the base class for the HTTPS listener.
025:         * 
026:         * @author <a href="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
027:         * @version $Id: HttpListener.java,v 1.15 2007/05/01 04:39:49 rickknowles Exp $
028:         */
029:        public class HttpListener implements  Listener, Runnable {
030:            protected static int LISTENER_TIMEOUT = 5000; // every 5s reset the
031:            // listener socket
032:            protected static int CONNECTION_TIMEOUT = 60000;
033:            protected static int BACKLOG_COUNT = 5000;
034:            protected static boolean DEFAULT_HNL = false;
035:            protected static int KEEP_ALIVE_TIMEOUT = 10000;
036:            protected static int KEEP_ALIVE_SLEEP = 20;
037:            protected static int KEEP_ALIVE_SLEEP_MAX = 500;
038:            protected HostGroup hostGroup;
039:            protected ObjectPool objectPool;
040:            protected boolean doHostnameLookups;
041:            protected int listenPort;
042:            protected String listenAddress;
043:            protected boolean interrupted;
044:
045:            protected HttpListener() {
046:            }
047:
048:            /**
049:             * Constructor
050:             */
051:            public HttpListener(Map args, ObjectPool objectPool,
052:                    HostGroup hostGroup) throws IOException {
053:                // Load resources
054:                this .hostGroup = hostGroup;
055:                this .objectPool = objectPool;
056:                this .listenPort = Integer.parseInt(WebAppConfiguration
057:                        .stringArg(args, getConnectorName() + "Port", ""
058:                                + getDefaultPort()));
059:                this .listenAddress = WebAppConfiguration.stringArg(args,
060:                        getConnectorName() + "ListenAddress", null);
061:                this .doHostnameLookups = WebAppConfiguration.booleanArg(args,
062:                        getConnectorName() + "DoHostnameLookups", DEFAULT_HNL);
063:            }
064:
065:            public boolean start() {
066:                if (this .listenPort < 0) {
067:                    return false;
068:                } else {
069:                    this .interrupted = false;
070:                    Thread thread = new Thread(this , Launcher.RESOURCES
071:                            .getString("Listener.ThreadName", new String[] {
072:                                    getConnectorName(), "" + this .listenPort }));
073:                    thread.setDaemon(true);
074:                    thread.start();
075:                    return true;
076:                }
077:            }
078:
079:            /**
080:             * The default port to use - this is just so that we can override for the
081:             * SSL connector.
082:             */
083:            protected int getDefaultPort() {
084:                return 8080;
085:            }
086:
087:            /**
088:             * The name to use when getting properties - this is just so that we can
089:             * override for the SSL connector.
090:             */
091:            protected String getConnectorName() {
092:                return getConnectorScheme();
093:            }
094:
095:            protected String getConnectorScheme() {
096:                return "http";
097:            }
098:
099:            /**
100:             * Gets a server socket - this is mostly for the purpose of allowing an
101:             * override in the SSL connector.
102:             */
103:            protected ServerSocket getServerSocket() throws IOException {
104:                ServerSocket ss = this .listenAddress == null ? new ServerSocket(
105:                        this .listenPort, BACKLOG_COUNT)
106:                        : new ServerSocket(this .listenPort, BACKLOG_COUNT,
107:                                InetAddress.getByName(this .listenAddress));
108:                return ss;
109:            }
110:
111:            /**
112:             * The main run method. This continually listens for incoming connections,
113:             * and allocates any that it finds to a request handler thread, before going
114:             * back to listen again.
115:             */
116:            public void run() {
117:                try {
118:                    ServerSocket ss = getServerSocket();
119:                    ss.setSoTimeout(LISTENER_TIMEOUT);
120:                    Logger.log(Logger.INFO, Launcher.RESOURCES,
121:                            "HttpListener.StartupOK", new String[] {
122:                                    getConnectorName().toUpperCase(),
123:                                    this .listenPort + "" });
124:
125:                    // Enter the main loop
126:                    while (!interrupted) {
127:                        // Get the listener
128:                        Socket s = null;
129:                        try {
130:                            s = ss.accept();
131:                        } catch (java.io.InterruptedIOException err) {
132:                            s = null;
133:                        }
134:
135:                        // if we actually got a socket, process it. Otherwise go around
136:                        // again
137:                        if (s != null)
138:                            this .objectPool.handleRequest(s, this );
139:                    }
140:
141:                    // Close server socket
142:                    ss.close();
143:                } catch (Throwable err) {
144:                    Logger.log(Logger.ERROR, Launcher.RESOURCES,
145:                            "HttpListener.ShutdownError", getConnectorName()
146:                                    .toUpperCase(), err);
147:                }
148:
149:                Logger.log(Logger.INFO, Launcher.RESOURCES,
150:                        "HttpListener.ShutdownOK", getConnectorName()
151:                                .toUpperCase());
152:            }
153:
154:            /**
155:             * Interrupts the listener thread. This will trigger a listener shutdown
156:             * once the so timeout has passed.
157:             */
158:            public void destroy() {
159:                this .interrupted = true;
160:            }
161:
162:            /**
163:             * Called by the request handler thread, because it needs specific setup
164:             * code for this connection's protocol (ie construction of request/response
165:             * objects, in/out streams, etc).
166:             * 
167:             * This implementation parses incoming AJP13 packets, and builds an
168:             * outputstream that is capable of writing back the response in AJP13
169:             * packets.
170:             */
171:            public void allocateRequestResponse(Socket socket,
172:                    InputStream inSocket, OutputStream outSocket,
173:                    RequestHandlerThread handler, boolean iAmFirst)
174:                    throws SocketException, IOException {
175:                Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
176:                        "HttpListener.AllocatingRequest", Thread
177:                                .currentThread().getName());
178:                socket.setSoTimeout(CONNECTION_TIMEOUT);
179:
180:                // Build input/output streams, plus request/response
181:                WinstoneInputStream inData = new WinstoneInputStream(inSocket);
182:                WinstoneOutputStream outData = new WinstoneOutputStream(
183:                        outSocket, false);
184:                WinstoneRequest req = this .objectPool.getRequestFromPool();
185:                WinstoneResponse rsp = this .objectPool.getResponseFromPool();
186:                outData.setResponse(rsp);
187:                req.setInputStream(inData);
188:                rsp.setOutputStream(outData);
189:                rsp.setRequest(req);
190:                // rsp.updateContentTypeHeader("text/html");
191:                req.setHostGroup(this .hostGroup);
192:
193:                // Set the handler's member variables so it can execute the servlet
194:                handler.setRequest(req);
195:                handler.setResponse(rsp);
196:                handler.setInStream(inData);
197:                handler.setOutStream(outData);
198:
199:                // If using this listener, we must set the server header now, because it
200:                // must be the first header. Ajp13 listener can defer to the Apache Server
201:                // header
202:                rsp.setHeader("Server", Launcher.RESOURCES
203:                        .getString("ServerVersion"));
204:            }
205:
206:            /**
207:             * Called by the request handler thread, because it needs specific shutdown
208:             * code for this connection's protocol (ie releasing input/output streams,
209:             * etc).
210:             */
211:            public void deallocateRequestResponse(RequestHandlerThread handler,
212:                    WinstoneRequest req, WinstoneResponse rsp,
213:                    WinstoneInputStream inData, WinstoneOutputStream outData)
214:                    throws IOException {
215:                handler.setInStream(null);
216:                handler.setOutStream(null);
217:                handler.setRequest(null);
218:                handler.setResponse(null);
219:                if (req != null)
220:                    this .objectPool.releaseRequestToPool(req);
221:                if (rsp != null)
222:                    this .objectPool.releaseResponseToPool(rsp);
223:            }
224:
225:            public String parseURI(RequestHandlerThread handler,
226:                    WinstoneRequest req, WinstoneResponse rsp,
227:                    WinstoneInputStream inData, Socket socket, boolean iAmFirst)
228:                    throws IOException {
229:                parseSocketInfo(socket, req);
230:
231:                // Read the header line (because this is the first line of the request,
232:                // apply keep-alive timeouts to it if we are not the first request)
233:                if (!iAmFirst) {
234:                    socket.setSoTimeout(KEEP_ALIVE_TIMEOUT);
235:                }
236:
237:                byte uriBuffer[] = null;
238:                try {
239:                    Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
240:                            "HttpListener.WaitingForURILine");
241:                    uriBuffer = inData.readLine();
242:                } catch (InterruptedIOException err) {
243:                    // keep alive timeout ? ignore if not first
244:                    if (iAmFirst) {
245:                        throw err;
246:                    } else {
247:                        return null;
248:                    }
249:                } finally {
250:                    try {
251:                        socket.setSoTimeout(CONNECTION_TIMEOUT);
252:                    } catch (Throwable err) {
253:                    }
254:                }
255:                handler.setRequestStartTime();
256:
257:                // Get header data (eg protocol, method, uri, headers, etc)
258:                String uriLine = new String(uriBuffer);
259:                if (uriLine.trim().equals(""))
260:                    throw new SocketException("Empty URI Line");
261:                String servletURI = parseURILine(uriLine, req, rsp);
262:                parseHeaders(req, inData);
263:                rsp.extractRequestKeepAliveHeader(req);
264:                int contentLength = req.getContentLength();
265:                if (contentLength != -1)
266:                    inData.setContentLength(contentLength);
267:                return servletURI;
268:            }
269:
270:            /**
271:             * Called by the request handler thread, because it needs specific shutdown
272:             * code for this connection's protocol if the keep-alive period expires (ie
273:             * closing sockets, etc).
274:             * 
275:             * This implementation simply shuts down the socket and streams.
276:             */
277:            public void releaseSocket(Socket socket, InputStream inSocket,
278:                    OutputStream outSocket) throws IOException {
279:                // Logger.log(Logger.FULL_DEBUG, "Releasing socket: " +
280:                // Thread.currentThread().getName());
281:                inSocket.close();
282:                outSocket.close();
283:                socket.close();
284:            }
285:
286:            protected void parseSocketInfo(Socket socket, WinstoneRequest req)
287:                    throws IOException {
288:                Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
289:                        "HttpListener.ParsingSocketInfo");
290:                req.setScheme(getConnectorScheme());
291:                req.setServerPort(socket.getLocalPort());
292:                req.setLocalPort(socket.getLocalPort());
293:                req.setLocalAddr(socket.getLocalAddress().getHostAddress());
294:                req.setRemoteIP(socket.getInetAddress().getHostAddress());
295:                req.setRemotePort(socket.getPort());
296:                if (this .doHostnameLookups) {
297:                    req.setServerName(socket.getLocalAddress().getHostName());
298:                    req.setRemoteName(socket.getInetAddress().getHostName());
299:                    req.setLocalName(socket.getLocalAddress().getHostName());
300:                } else {
301:                    req
302:                            .setServerName(socket.getLocalAddress()
303:                                    .getHostAddress());
304:                    req.setRemoteName(socket.getInetAddress().getHostAddress());
305:                    req.setLocalName(socket.getLocalAddress().getHostAddress());
306:                }
307:            }
308:
309:            /**
310:             * Tries to wait for extra requests on the same socket. If any are found
311:             * before the timeout expires, it exits with a true, indicating a new
312:             * request is waiting. If the protocol does not support keep-alives, or the
313:             * request instructed us to close the connection, or the timeout expires,
314:             * return a false, instructing the handler thread to begin shutting down the
315:             * socket and relase itself.
316:             */
317:            public boolean processKeepAlive(WinstoneRequest request,
318:                    WinstoneResponse response, InputStream inSocket)
319:                    throws IOException, InterruptedException {
320:                // Try keep alive if allowed
321:                boolean continueFlag = !response.closeAfterRequest();
322:                return continueFlag;
323:            }
324:
325:            /**
326:             * Processes the uri line into it's component parts, determining protocol,
327:             * method and uri
328:             */
329:            private String parseURILine(String uriLine, WinstoneRequest req,
330:                    WinstoneResponse rsp) {
331:                Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
332:                        "HttpListener.UriLine", uriLine.trim());
333:
334:                // Method
335:                int spacePos = uriLine.indexOf(' ');
336:                if (spacePos == -1)
337:                    throw new WinstoneException(Launcher.RESOURCES.getString(
338:                            "HttpListener.ErrorUriLine", uriLine));
339:                String method = uriLine.substring(0, spacePos).toUpperCase();
340:                String fullURI = null;
341:
342:                // URI
343:                String remainder = uriLine.substring(spacePos + 1);
344:                spacePos = remainder.indexOf(' ');
345:                if (spacePos == -1) {
346:                    fullURI = trimHostName(remainder.trim());
347:                    req.setProtocol("HTTP/0.9");
348:                    rsp.setProtocol("HTTP/0.9");
349:                } else {
350:                    fullURI = trimHostName(remainder.substring(0, spacePos)
351:                            .trim());
352:                    String protocol = remainder.substring(spacePos + 1).trim()
353:                            .toUpperCase();
354:                    req.setProtocol(protocol);
355:                    rsp.setProtocol(protocol);
356:                }
357:
358:                req.setMethod(method);
359:                // req.setRequestURI(fullURI);
360:                return fullURI;
361:            }
362:
363:            private String trimHostName(String input) {
364:                if (input == null)
365:                    return null;
366:                else if (input.startsWith("/"))
367:                    return input;
368:
369:                int hostStart = input.indexOf("://");
370:                if (hostStart == -1)
371:                    return input;
372:                String hostName = input.substring(hostStart + 3);
373:                int pathStart = hostName.indexOf('/');
374:                if (pathStart == -1)
375:                    return "/";
376:                else
377:                    return hostName.substring(pathStart);
378:            }
379:
380:            /**
381:             * Parse the incoming stream into a list of headers (stopping at the first
382:             * blank line), then call the parseHeaders(req, list) method on that list.
383:             */
384:            public void parseHeaders(WinstoneRequest req,
385:                    WinstoneInputStream inData) throws IOException {
386:                List headerList = new ArrayList();
387:
388:                if (!req.getProtocol().startsWith("HTTP/0")) {
389:                    // Loop to get headers
390:                    byte headerBuffer[] = inData.readLine();
391:                    String headerLine = new String(headerBuffer);
392:
393:                    while (headerLine.trim().length() > 0) {
394:                        if (headerLine.indexOf(':') != -1) {
395:                            headerList.add(headerLine.trim());
396:                            Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
397:                                    "HttpListener.Header", headerLine.trim());
398:                        }
399:                        headerBuffer = inData.readLine();
400:                        headerLine = new String(headerBuffer);
401:                    }
402:                }
403:
404:                // If no headers available, parse an empty list
405:                req.parseHeaders(headerList);
406:            }
407:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.