Source Code Cross Referenced for Ajp13Listener.java in  » Web-Server » Winstone » winstone » ajp13 » 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.ajp13 
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.ajp13;
008:
009:        import java.io.ByteArrayInputStream;
010:        import java.io.IOException;
011:        import java.io.InputStream;
012:        import java.io.InterruptedIOException;
013:        import java.io.OutputStream;
014:        import java.io.UnsupportedEncodingException;
015:        import java.net.InetAddress;
016:        import java.net.ServerSocket;
017:        import java.net.Socket;
018:        import java.net.SocketException;
019:        import java.security.cert.CertificateException;
020:        import java.security.cert.CertificateFactory;
021:        import java.security.cert.X509Certificate;
022:        import java.util.Arrays;
023:        import java.util.Iterator;
024:        import java.util.Map;
025:
026:        import winstone.HostGroup;
027:        import winstone.Launcher;
028:        import winstone.Listener;
029:        import winstone.Logger;
030:        import winstone.ObjectPool;
031:        import winstone.RequestHandlerThread;
032:        import winstone.WebAppConfiguration;
033:        import winstone.WinstoneException;
034:        import winstone.WinstoneInputStream;
035:        import winstone.WinstoneOutputStream;
036:        import winstone.WinstoneRequest;
037:        import winstone.WinstoneResourceBundle;
038:        import winstone.WinstoneResponse;
039:
040:        /**
041:         * Implements the main listener daemon thread. This is the class that gets
042:         * launched by the command line, and owns the server socket, etc.
043:         * 
044:         * @author mailto: <a href="rick_knowles@hotmail.com">Rick Knowles</a>
045:         * @version $Id: Ajp13Listener.java,v 1.12 2006/03/24 17:24:22 rickknowles Exp $
046:         */
047:        public class Ajp13Listener implements  Listener, Runnable {
048:            public final static WinstoneResourceBundle AJP_RESOURCES = new WinstoneResourceBundle(
049:                    "winstone.ajp13.LocalStrings");
050:
051:            private final static int LISTENER_TIMEOUT = 5000; // every 5s reset the listener socket
052:            private final static int DEFAULT_PORT = 8009;
053:            private final static int CONNECTION_TIMEOUT = 60000;
054:            private final static int BACKLOG_COUNT = 1000;
055:            private final static int KEEP_ALIVE_TIMEOUT = -1;
056:            //    private final static int KEEP_ALIVE_SLEEP = 50;
057:            //    private final static int KEEP_ALIVE_SLEEP_MAX = 500;
058:            private final static String TEMPORARY_URL_STASH = "winstone.ajp13.TemporaryURLAttribute";
059:
060:            private HostGroup hostGroup;
061:            private ObjectPool objectPool;
062:            private int listenPort;
063:            private boolean interrupted;
064:            private String listenAddress;
065:
066:            /**
067:             * Constructor
068:             */
069:            public Ajp13Listener(Map args, ObjectPool objectPool,
070:                    HostGroup hostGroup) {
071:                // Load resources
072:                this .hostGroup = hostGroup;
073:                this .objectPool = objectPool;
074:
075:                this .listenPort = Integer.parseInt(WebAppConfiguration
076:                        .stringArg(args, "ajp13Port", "" + DEFAULT_PORT));
077:                this .listenAddress = WebAppConfiguration.stringArg(args,
078:                        "ajp13ListenAddress", null);
079:            }
080:
081:            public boolean start() {
082:                if (this .listenPort < 0) {
083:                    return false;
084:                } else {
085:                    this .interrupted = false;
086:                    Thread thread = new Thread(this , Launcher.RESOURCES
087:                            .getString("Listener.ThreadName", new String[] {
088:                                    "ajp13", "" + this .listenPort }));
089:                    thread.setDaemon(true);
090:                    thread.start();
091:                    return true;
092:                }
093:            }
094:
095:            /**
096:             * The main run method. This handles the normal thread processing.
097:             */
098:            public void run() {
099:                try {
100:                    ServerSocket ss = this .listenAddress == null ? new ServerSocket(
101:                            this .listenPort, BACKLOG_COUNT)
102:                            : new ServerSocket(this .listenPort, BACKLOG_COUNT,
103:                                    InetAddress.getByName(this .listenAddress));
104:                    ss.setSoTimeout(LISTENER_TIMEOUT);
105:                    Logger.log(Logger.INFO, AJP_RESOURCES,
106:                            "Ajp13Listener.StartupOK", this .listenPort + "");
107:
108:                    // Enter the main loop
109:                    while (!interrupted) {
110:                        // Get the listener
111:                        Socket s = null;
112:                        try {
113:                            s = ss.accept();
114:                        } catch (java.io.InterruptedIOException err) {
115:                            s = null;
116:                        }
117:
118:                        // if we actually got a socket, process it. Otherwise go around
119:                        // again
120:                        if (s != null)
121:                            this .objectPool.handleRequest(s, this );
122:                    }
123:
124:                    // Close server socket
125:                    ss.close();
126:                } catch (Throwable err) {
127:                    Logger.log(Logger.ERROR, AJP_RESOURCES,
128:                            "Ajp13Listener.ShutdownError", err);
129:                }
130:
131:                Logger.log(Logger.INFO, AJP_RESOURCES,
132:                        "Ajp13Listener.ShutdownOK");
133:            }
134:
135:            /**
136:             * Interrupts the listener thread. This will trigger a listener shutdown
137:             * once the so timeout has passed.
138:             */
139:            public void destroy() {
140:                this .interrupted = true;
141:            }
142:
143:            /**
144:             * Called by the request handler thread, because it needs specific setup
145:             * code for this connection's protocol (ie construction of request/response
146:             * objects, in/out streams, etc).
147:             * 
148:             * This implementation parses incoming AJP13 packets, and builds an
149:             * outputstream that is capable of writing back the response in AJP13
150:             * packets.
151:             */
152:            public void allocateRequestResponse(Socket socket,
153:                    InputStream inSocket, OutputStream outSocket,
154:                    RequestHandlerThread handler, boolean iAmFirst)
155:                    throws SocketException, IOException {
156:                WinstoneRequest req = this .objectPool.getRequestFromPool();
157:                WinstoneResponse rsp = this .objectPool.getResponseFromPool();
158:                rsp.setRequest(req);
159:                req.setHostGroup(this .hostGroup);
160:                // rsp.updateContentTypeHeader("text/html");
161:
162:                if (iAmFirst || (KEEP_ALIVE_TIMEOUT == -1))
163:                    socket.setSoTimeout(CONNECTION_TIMEOUT);
164:                else
165:                    socket.setSoTimeout(KEEP_ALIVE_TIMEOUT);
166:                Ajp13IncomingPacket headers = null;
167:                try {
168:                    headers = new Ajp13IncomingPacket(inSocket, handler);
169:                } catch (InterruptedIOException err) {
170:                    // keep alive timeout ? ignore if not first
171:                    if (iAmFirst) {
172:                        throw err;
173:                    } else {
174:                        deallocateRequestResponse(handler, req, rsp, null, null);
175:                        return;
176:                    }
177:                } finally {
178:                    try {
179:                        socket.setSoTimeout(CONNECTION_TIMEOUT);
180:                    } catch (Throwable err) {
181:                    }
182:                }
183:
184:                if (headers.getPacketLength() > 0) {
185:                    headers.parsePacket("8859_1");
186:                    parseSocketInfo(headers, req);
187:                    req.parseHeaders(Arrays.asList(headers.getHeaders()));
188:                    String servletURI = parseURILine(headers, req, rsp);
189:                    req.setAttribute(TEMPORARY_URL_STASH, servletURI);
190:
191:                    // If content-length present and non-zero, download the other
192:                    // packets
193:                    WinstoneInputStream inData = null;
194:                    int contentLength = req.getContentLength();
195:                    if (contentLength > 0) {
196:                        byte bodyContent[] = new byte[contentLength];
197:                        int position = 0;
198:                        while (position < contentLength) {
199:                            outSocket.write(getBodyRequestPacket(Math.min(
200:                                    contentLength - position, 8184)));
201:                            position = getBodyResponsePacket(inSocket,
202:                                    bodyContent, position);
203:                            Logger.log(Logger.FULL_DEBUG, AJP_RESOURCES,
204:                                    "Ajp13Listener.ReadBodyProgress",
205:                                    new String[] { "" + position,
206:                                            "" + contentLength });
207:
208:                        }
209:                        inData = new WinstoneInputStream(bodyContent);
210:                        inData.setContentLength(contentLength);
211:                    } else
212:                        inData = new WinstoneInputStream(new byte[0]);
213:                    req.setInputStream(inData);
214:
215:                    // Build input/output streams, plus request/response
216:                    WinstoneOutputStream outData = new Ajp13OutputStream(socket
217:                            .getOutputStream(), "8859_1");
218:                    outData.setResponse(rsp);
219:                    rsp.setOutputStream(outData);
220:
221:                    // Set the handler's member variables so it can execute the servlet
222:                    handler.setRequest(req);
223:                    handler.setResponse(rsp);
224:                    handler.setInStream(inData);
225:                    handler.setOutStream(outData);
226:                }
227:            }
228:
229:            /**
230:             * Called by the request handler thread, because it needs specific shutdown
231:             * code for this connection's protocol (ie releasing input/output streams,
232:             * etc).
233:             */
234:            public void deallocateRequestResponse(RequestHandlerThread handler,
235:                    WinstoneRequest req, WinstoneResponse rsp,
236:                    WinstoneInputStream inData, WinstoneOutputStream outData)
237:                    throws IOException {
238:                handler.setInStream(null);
239:                handler.setOutStream(null);
240:                handler.setRequest(null);
241:                handler.setResponse(null);
242:                if (req != null)
243:                    this .objectPool.releaseRequestToPool(req);
244:                if (rsp != null)
245:                    this .objectPool.releaseResponseToPool(rsp);
246:            }
247:
248:            /**
249:             * This is kind of a hack, since we have already parsed the uri to get the
250:             * input stream. Just pass back the request uri
251:             */
252:            public String parseURI(RequestHandlerThread handler,
253:                    WinstoneRequest req, WinstoneResponse rsp,
254:                    WinstoneInputStream inData, Socket socket, boolean iAmFirst)
255:                    throws IOException {
256:                String uri = (String) req.getAttribute(TEMPORARY_URL_STASH);
257:                req.removeAttribute(TEMPORARY_URL_STASH);
258:                return uri;
259:            }
260:
261:            /**
262:             * Called by the request handler thread, because it needs specific shutdown
263:             * code for this connection's protocol if the keep-alive period expires (ie
264:             * closing sockets, etc).
265:             * 
266:             * This implementation simply shuts down the socket and streams.
267:             */
268:            public void releaseSocket(Socket socket, InputStream inSocket,
269:                    OutputStream outSocket) throws IOException {
270:                // Logger.log(Logger.FULL_DEBUG, "Releasing socket: " +
271:                // Thread.currentThread().getName());
272:                inSocket.close();
273:                outSocket.close();
274:                socket.close();
275:            }
276:
277:            /**
278:             * Extract the header details relating to socket stuff from the ajp13 header
279:             * packet
280:             */
281:            private void parseSocketInfo(Ajp13IncomingPacket headers,
282:                    WinstoneRequest req) {
283:                req.setServerPort(headers.getServerPort());
284:                req.setRemoteIP(headers.getRemoteAddress());
285:                req.setServerName(headers.getServerName());
286:                req.setLocalPort(headers.getServerPort());
287:                req.setLocalAddr(headers.getServerName());
288:                req.setRemoteIP(headers.getRemoteAddress());
289:                if ((headers.getRemoteHost() != null)
290:                        && !headers.getRemoteHost().equals(""))
291:                    req.setRemoteName(headers.getRemoteHost());
292:                else
293:                    req.setRemoteName(headers.getRemoteAddress());
294:                req.setScheme(headers.isSSL() ? "https" : "http");
295:                req.setIsSecure(headers.isSSL());
296:            }
297:
298:            /**
299:             * Extract the header details relating to protocol, uri, etc from the ajp13
300:             * header packet
301:             */
302:            private String parseURILine(Ajp13IncomingPacket headers,
303:                    WinstoneRequest req, WinstoneResponse rsp)
304:                    throws UnsupportedEncodingException {
305:                req.setMethod(headers.getMethod());
306:                req.setProtocol(headers.getProtocol());
307:                rsp.setProtocol(headers.getProtocol());
308:                rsp.extractRequestKeepAliveHeader(req);
309:                // req.setServletPath(headers.getURI());
310:                // req.setRequestURI(headers.getURI());
311:
312:                // Get query string if supplied
313:                for (Iterator i = headers.getAttributes().keySet().iterator(); i
314:                        .hasNext();) {
315:                    String attName = (String) i.next();
316:                    if (attName.equals("query_string")) {
317:                        String qs = (String) headers.getAttributes().get(
318:                                "query_string");
319:                        req.setQueryString(qs);
320:                        // req.getParameters().putAll(WinstoneRequest.extractParameters(qs,
321:                        // req.getEncoding(), mainResources));
322:                        // req.setRequestURI(headers.getURI() + "?" + qs);
323:                    } else if (attName.equals("ssl_cert")) {
324:                        String certValue = (String) headers.getAttributes()
325:                                .get("ssl_cert");
326:                        InputStream certStream = new ByteArrayInputStream(
327:                                certValue.getBytes("8859_1"));
328:                        X509Certificate certificateArray[] = new X509Certificate[1];
329:                        try {
330:                            certificateArray[0] = (X509Certificate) CertificateFactory
331:                                    .getInstance("X.509").generateCertificate(
332:                                            certStream);
333:                        } catch (CertificateException err) {
334:                            Logger.log(Logger.DEBUG, AJP_RESOURCES,
335:                                    "Ajp13Listener.SkippingCert", certValue);
336:                        }
337:                        req.setAttribute(
338:                                "javax.servlet.request.X509Certificate",
339:                                certificateArray);
340:                        req.setIsSecure(true);
341:                    } else if (attName.equals("ssl_cipher")) {
342:                        String cipher = (String) headers.getAttributes().get(
343:                                "ssl_cipher");
344:                        req.setAttribute("javax.servlet.request.cipher_suite",
345:                                cipher);
346:                        req.setAttribute("javax.servlet.request.key_size",
347:                                getKeySize(cipher));
348:                        req.setIsSecure(true);
349:                    } else if (attName.equals("ssl_session")) {
350:                        req.setAttribute("javax.servlet.request.ssl_session",
351:                                headers.getAttributes().get("ssl_session"));
352:                        req.setIsSecure(true);
353:                    } else
354:                        Logger.log(Logger.DEBUG, AJP_RESOURCES,
355:                                "Ajp13Listener.UnknownAttribute", new String[] {
356:                                        attName,
357:                                        ""
358:                                                + headers.getAttributes().get(
359:                                                        attName) });
360:                }
361:                return headers.getURI();
362:
363:            }
364:
365:            private Integer getKeySize(String cipherSuite) {
366:                if (cipherSuite.indexOf("_WITH_NULL_") != -1)
367:                    return new Integer(0);
368:                else if (cipherSuite.indexOf("_WITH_IDEA_CBC_") != -1)
369:                    return new Integer(128);
370:                else if (cipherSuite.indexOf("_WITH_RC2_CBC_40_") != -1)
371:                    return new Integer(40);
372:                else if (cipherSuite.indexOf("_WITH_RC4_40_") != -1)
373:                    return new Integer(40);
374:                else if (cipherSuite.indexOf("_WITH_RC4_128_") != -1)
375:                    return new Integer(128);
376:                else if (cipherSuite.indexOf("_WITH_DES40_CBC_") != -1)
377:                    return new Integer(40);
378:                else if (cipherSuite.indexOf("_WITH_DES_CBC_") != -1)
379:                    return new Integer(56);
380:                else if (cipherSuite.indexOf("_WITH_3DES_EDE_CBC_") != -1)
381:                    return new Integer(168);
382:                else
383:                    return null;
384:            }
385:
386:            /**
387:             * Tries to wait for extra requests on the same socket. If any are found
388:             * before the timeout expires, it exits with a true, indicating a new
389:             * request is waiting. If the timeout expires, return a false, instructing
390:             * the handler thread to begin shutting down the socket and relase itself.
391:             */
392:            public boolean processKeepAlive(WinstoneRequest request,
393:                    WinstoneResponse response, InputStream inSocket)
394:                    throws IOException, InterruptedException {
395:                return true;
396:            }
397:
398:            /**
399:             * Build the packet needed for asking for a body chunk
400:             */
401:            private byte[] getBodyRequestPacket(int desiredPacketLength) {
402:                byte getBodyRequestPacket[] = new byte[] { 0x41, 0x42, 0x00,
403:                        0x03, 0x06, 0x00, 0x00 };
404:                Ajp13OutputStream.setIntBlock(desiredPacketLength,
405:                        getBodyRequestPacket, 5);
406:                return getBodyRequestPacket;
407:            }
408:
409:            /**
410:             * Process the server response to a get_body_chunk request. This loads the
411:             * packet from the stream, and unpacks it into the buffer at the right
412:             * place.
413:             */
414:            private int getBodyResponsePacket(InputStream in, byte buffer[],
415:                    int offset) throws IOException {
416:                // Get the incoming packet flag
417:                byte headerBuffer[] = new byte[4];
418:                int headerBytesRead = in.read(headerBuffer);
419:                if (headerBytesRead != 4)
420:                    throw new WinstoneException(AJP_RESOURCES
421:                            .getString("Ajp13Listener.InvalidHeader"));
422:                else if ((headerBuffer[0] != 0x12) || (headerBuffer[1] != 0x34))
423:                    throw new WinstoneException(AJP_RESOURCES
424:                            .getString("Ajp13Listener.InvalidHeader"));
425:
426:                // Read in the whole packet
427:                int packetLength = ((headerBuffer[2] & 0xFF) << 8)
428:                        + (headerBuffer[3] & 0xFF);
429:                if (packetLength == 0)
430:                    return offset;
431:
432:                // Look for packet length
433:                byte bodyLengthBuffer[] = new byte[2];
434:                in.read(bodyLengthBuffer);
435:                int bodyLength = ((bodyLengthBuffer[0] & 0xFF) << 8)
436:                        + (bodyLengthBuffer[1] & 0xFF);
437:                int packetBytesRead = in.read(buffer, offset, bodyLength);
438:
439:                if (packetBytesRead < bodyLength)
440:                    throw new WinstoneException(AJP_RESOURCES
441:                            .getString("Ajp13Listener.ShortPacket"));
442:                else
443:                    return packetBytesRead + offset;
444:            }
445:            //
446:            //    /**
447:            //     * Useful method for dumping out the contents of a packet in hex form
448:            //     */
449:            //    public static void packetDump(byte packetBytes[], int packetLength) {
450:            //        String dump = "";
451:            //        for (int n = 0; n < packetLength; n+=16) {
452:            //            String line = Integer.toHexString((n >> 4) & 0xF) + "0:";
453:            //            for (int j = 0; j < Math.min(packetLength - n, 16); j++)
454:            //            line = line + " " + ((packetBytes[n + j] & 0xFF) < 16 ? "0" : "") +
455:            //            Integer.toHexString(packetBytes[n + j] & 0xFF);
456:            //       
457:            //            line = line + "    ";
458:            //            for (int j = 0; j < Math.min(packetLength - n, 16); j++) {
459:            //                byte me = (byte) (packetBytes[n + j] & 0xFF);
460:            //                line = line + (((me > 32) && (me < 123)) ? (char) me : '.');
461:            //            }
462:            //            dump = dump + line + "\r\n";
463:            //        }
464:            //        System.out.println(dump);
465:            //    }
466:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.