Source Code Cross Referenced for HttpProcessor.java in  » Web-Server » Rimfaxe-Web-Server » org » apache » catalina » connector » http » 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 » Rimfaxe Web Server » org.apache.catalina.connector.http 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http/HttpProcessor.java,v 1.46 2002/04/04 17:50:34 remm Exp $
0002:         * $Revision: 1.46 $
0003:         * $Date: 2002/04/04 17:50:34 $
0004:         *
0005:         * ====================================================================
0006:         *
0007:         * The Apache Software License, Version 1.1
0008:         *
0009:         * Copyright (c) 1999 The Apache Software Foundation.  All rights
0010:         * reserved.
0011:         *
0012:         * Redistribution and use in source and binary forms, with or without
0013:         * modification, are permitted provided that the following conditions
0014:         * are met:
0015:         *
0016:         * 1. Redistributions of source code must retain the above copyright
0017:         *    notice, this list of conditions and the following disclaimer.
0018:         *
0019:         * 2. Redistributions in binary form must reproduce the above copyright
0020:         *    notice, this list of conditions and the following disclaimer in
0021:         *    the documentation and/or other materials provided with the
0022:         *    distribution.
0023:         *
0024:         * 3. The end-user documentation included with the redistribution, if
0025:         *    any, must include the following acknowlegement:
0026:         *       "This product includes software developed by the
0027:         *        Apache Software Foundation (http://www.apache.org/)."
0028:         *    Alternately, this acknowlegement may appear in the software itself,
0029:         *    if and wherever such third-party acknowlegements normally appear.
0030:         *
0031:         * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
0032:         *    Foundation" must not be used to endorse or promote products derived
0033:         *    from this software without prior written permission. For written
0034:         *    permission, please contact apache@apache.org.
0035:         *
0036:         * 5. Products derived from this software may not be called "Apache"
0037:         *    nor may "Apache" appear in their names without prior written
0038:         *    permission of the Apache Group.
0039:         *
0040:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0041:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0042:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0043:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0044:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0045:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0046:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0047:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0048:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0049:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0050:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0051:         * SUCH DAMAGE.
0052:         * ====================================================================
0053:         *
0054:         * This software consists of voluntary contributions made by many
0055:         * individuals on behalf of the Apache Software Foundation.  For more
0056:         * information on the Apache Software Foundation, please see
0057:         * <http://www.apache.org/>.
0058:         *
0059:         * [Additional notices, if required by prior licensing conditions]
0060:         *
0061:         */
0062:
0063:        package org.apache.catalina.connector.http;
0064:
0065:        import java.io.BufferedInputStream;
0066:        import java.io.EOFException;
0067:        import java.io.InterruptedIOException;
0068:        import java.io.InputStream;
0069:        import java.io.IOException;
0070:        import java.io.OutputStream;
0071:        import java.net.InetAddress;
0072:        import java.net.Socket;
0073:        import java.util.ArrayList;
0074:        import java.util.Iterator;
0075:        import java.util.Locale;
0076:        import java.util.StringTokenizer;
0077:        import java.util.TreeMap;
0078:        import javax.servlet.ServletException;
0079:        import javax.servlet.http.Cookie;
0080:        import javax.servlet.http.HttpServletRequest;
0081:        import javax.servlet.http.HttpServletResponse;
0082:        import org.apache.catalina.Connector;
0083:        import org.apache.catalina.Container;
0084:        import org.apache.catalina.Globals;
0085:        import org.apache.catalina.HttpRequest;
0086:        import org.apache.catalina.HttpResponse;
0087:        import org.apache.catalina.Lifecycle;
0088:        import org.apache.catalina.LifecycleEvent;
0089:        import org.apache.catalina.LifecycleException;
0090:        import org.apache.catalina.LifecycleListener;
0091:        import org.apache.catalina.Logger;
0092:        import org.apache.catalina.util.FastHttpDateFormat;
0093:        import org.apache.catalina.util.LifecycleSupport;
0094:        import org.apache.catalina.util.RequestUtil;
0095:        import org.apache.catalina.util.ServerInfo;
0096:        import org.apache.catalina.util.StringManager;
0097:        import org.apache.catalina.util.StringParser;
0098:
0099:        /**
0100:         * Implementation of a request processor (and its associated thread) that may
0101:         * be used by an HttpConnector to process individual requests.  The connector
0102:         * will allocate a processor from its pool, assign a particular socket to it,
0103:         * and the processor will then execute the processing required to complete
0104:         * the request.  When the processor is completed, it will recycle itself.
0105:         *
0106:         * @author Craig R. McClanahan
0107:         * @author Remy Maucherat
0108:         * @version $Revision: 1.46 $ $Date: 2002/04/04 17:50:34 $
0109:         * @deprecated
0110:         */
0111:
0112:        final class HttpProcessor implements  Lifecycle, Runnable {
0113:
0114:            // ----------------------------------------------------- Manifest Constants
0115:
0116:            /**
0117:             * Server information string for this server.
0118:             */
0119:            private static final String SERVER_INFO = ServerInfo
0120:                    .getServerInfo()
0121:                    + " (HTTP/1.1 Connector)";
0122:
0123:            // ----------------------------------------------------------- Constructors
0124:
0125:            /**
0126:             * Construct a new HttpProcessor associated with the specified connector.
0127:             *
0128:             * @param connector HttpConnector that owns this processor
0129:             * @param id Identifier of this HttpProcessor (unique per connector)
0130:             */
0131:            public HttpProcessor(HttpConnector connector, int id) {
0132:
0133:                super ();
0134:                this .connector = connector;
0135:                this .debug = connector.getDebug();
0136:                this .id = id;
0137:                this .proxyName = connector.getProxyName();
0138:                this .proxyPort = connector.getProxyPort();
0139:                this .request = (HttpRequestImpl) connector.createRequest();
0140:                this .response = (HttpResponseImpl) connector.createResponse();
0141:                this .serverPort = connector.getPort();
0142:                this .threadName = "HttpProcessor[" + connector.getPort() + "]["
0143:                        + id + "]";
0144:
0145:            }
0146:
0147:            // ----------------------------------------------------- Instance Variables
0148:
0149:            /**
0150:             * Is there a new socket available?
0151:             */
0152:            private boolean available = false;
0153:
0154:            /**
0155:             * The HttpConnector with which this processor is associated.
0156:             */
0157:            private HttpConnector connector = null;
0158:
0159:            /**
0160:             * The debugging detail level for this component.
0161:             */
0162:            private int debug = 0;
0163:
0164:            /**
0165:             * The identifier of this processor, unique per connector.
0166:             */
0167:            private int id = 0;
0168:
0169:            /**
0170:             * The lifecycle event support for this component.
0171:             */
0172:            private LifecycleSupport lifecycle = new LifecycleSupport(this );
0173:
0174:            /**
0175:             * The match string for identifying a session ID parameter.
0176:             */
0177:            private static final String match = ";"
0178:                    + Globals.SESSION_PARAMETER_NAME + "=";
0179:
0180:            /**
0181:             * The match string for identifying a session ID parameter.
0182:             */
0183:            private static final char[] SESSION_ID = match.toCharArray();
0184:
0185:            /**
0186:             * The string parser we will use for parsing request lines.
0187:             */
0188:            private StringParser parser = new StringParser();
0189:
0190:            /**
0191:             * The proxy server name for our Connector.
0192:             */
0193:            private String proxyName = null;
0194:
0195:            /**
0196:             * The proxy server port for our Connector.
0197:             */
0198:            private int proxyPort = 0;
0199:
0200:            /**
0201:             * The HTTP request object we will pass to our associated container.
0202:             */
0203:            private HttpRequestImpl request = null;
0204:
0205:            /**
0206:             * The HTTP response object we will pass to our associated container.
0207:             */
0208:            private HttpResponseImpl response = null;
0209:
0210:            /**
0211:             * The actual server port for our Connector.
0212:             */
0213:            private int serverPort = 0;
0214:
0215:            /**
0216:             * The string manager for this package.
0217:             */
0218:            protected StringManager sm = StringManager
0219:                    .getManager(Constants.Package);
0220:
0221:            /**
0222:             * The socket we are currently processing a request for.  This object
0223:             * is used for inter-thread communication only.
0224:             */
0225:            private Socket socket = null;
0226:
0227:            /**
0228:             * Has this component been started yet?
0229:             */
0230:            private boolean started = false;
0231:
0232:            /**
0233:             * The shutdown signal to our background thread
0234:             */
0235:            private boolean stopped = false;
0236:
0237:            /**
0238:             * The background thread.
0239:             */
0240:            private Thread thread = null;
0241:
0242:            /**
0243:             * The name to register for the background thread.
0244:             */
0245:            private String threadName = null;
0246:
0247:            /**
0248:             * The thread synchronization object.
0249:             */
0250:            private Object threadSync = new Object();
0251:
0252:            /**
0253:             * Keep alive indicator.
0254:             */
0255:            private boolean keepAlive = false;
0256:
0257:            /**
0258:             * HTTP/1.1 client.
0259:             */
0260:            private boolean http11 = true;
0261:
0262:            /**
0263:             * True if the client has asked to recieve a request acknoledgement. If so
0264:             * the server will send a preliminary 100 Continue response just after it
0265:             * has successfully parsed the request headers, and before starting
0266:             * reading the request entity body.
0267:             */
0268:            private boolean sendAck = false;
0269:
0270:            /**
0271:             * Ack string when pipelining HTTP requests.
0272:             */
0273:            private static final byte[] ack = (new String(
0274:                    "HTTP/1.1 100 Continue\r\n\r\n")).getBytes();
0275:
0276:            /**
0277:             * CRLF.
0278:             */
0279:            private static final byte[] CRLF = (new String("\r\n")).getBytes();
0280:
0281:            /**
0282:             * Line buffer.
0283:             */
0284:            //private char[] lineBuffer = new char[4096];
0285:
0286:            /**
0287:             * Request line buffer.
0288:             */
0289:            private HttpRequestLine requestLine = new HttpRequestLine();
0290:
0291:            /**
0292:             * Processor state
0293:             */
0294:            private int status = Constants.PROCESSOR_IDLE;
0295:
0296:            // --------------------------------------------------------- Public Methods
0297:
0298:            /**
0299:             * Return a String value representing this object.
0300:             */
0301:            public String toString() {
0302:
0303:                return (this .threadName);
0304:
0305:            }
0306:
0307:            // -------------------------------------------------------- Package Methods
0308:
0309:            /**
0310:             * Process an incoming TCP/IP connection on the specified socket.  Any
0311:             * exception that occurs during processing must be logged and swallowed.
0312:             * <b>NOTE</b>:  This method is called from our Connector's thread.  We
0313:             * must assign it to our own thread so that multiple simultaneous
0314:             * requests can be handled.
0315:             *
0316:             * @param socket TCP socket to process
0317:             */
0318:            synchronized void assign(Socket socket) {
0319:
0320:                // Wait for the Processor to get the previous Socket
0321:                while (available) {
0322:                    try {
0323:                        wait();
0324:                    } catch (InterruptedException e) {
0325:                    }
0326:                }
0327:
0328:                // Store the newly available Socket and notify our thread
0329:                this .socket = socket;
0330:                available = true;
0331:                notifyAll();
0332:
0333:                if ((debug >= 1) && (socket != null))
0334:                    log(" An incoming request is being assigned");
0335:
0336:            }
0337:
0338:            // -------------------------------------------------------- Private Methods
0339:
0340:            /**
0341:             * Await a newly assigned Socket from our Connector, or <code>null</code>
0342:             * if we are supposed to shut down.
0343:             */
0344:            private synchronized Socket await() {
0345:
0346:                // Wait for the Connector to provide a new Socket
0347:                while (!available) {
0348:                    try {
0349:                        wait();
0350:                    } catch (InterruptedException e) {
0351:                    }
0352:                }
0353:
0354:                // Notify the Connector that we have received this Socket
0355:                Socket socket = this .socket;
0356:                available = false;
0357:                notifyAll();
0358:
0359:                if ((debug >= 1) && (socket != null))
0360:                    log("  The incoming request has been awaited");
0361:
0362:                return (socket);
0363:
0364:            }
0365:
0366:            /**
0367:             * Log a message on the Logger associated with our Container (if any)
0368:             *
0369:             * @param message Message to be logged
0370:             */
0371:            private void log(String message) {
0372:
0373:                Logger logger = connector.getContainer().getLogger();
0374:                if (logger != null)
0375:                    logger.log(threadName + " " + message);
0376:
0377:            }
0378:
0379:            /**
0380:             * Log a message on the Logger associated with our Container (if any)
0381:             *
0382:             * @param message Message to be logged
0383:             * @param throwable Associated exception
0384:             */
0385:            private void log(String message, Throwable throwable) {
0386:
0387:                Logger logger = connector.getContainer().getLogger();
0388:                if (logger != null)
0389:                    logger.log(threadName + " " + message, throwable);
0390:
0391:            }
0392:
0393:            /**
0394:             * Parse the value of an <code>Accept-Language</code> header, and add
0395:             * the corresponding Locales to the current request.
0396:             *
0397:             * @param value The value of the <code>Accept-Language</code> header.
0398:             */
0399:            private void parseAcceptLanguage(String value) {
0400:
0401:                // Store the accumulated languages that have been requested in
0402:                // a local collection, sorted by the quality value (so we can
0403:                // add Locales in descending order).  The values will be ArrayLists
0404:                // containing the corresponding Locales to be added
0405:                TreeMap locales = new TreeMap();
0406:
0407:                // Preprocess the value to remove all whitespace
0408:                int white = value.indexOf(' ');
0409:                if (white < 0)
0410:                    white = value.indexOf('\t');
0411:                if (white >= 0) {
0412:                    StringBuffer sb = new StringBuffer();
0413:                    int len = value.length();
0414:                    for (int i = 0; i < len; i++) {
0415:                        char ch = value.charAt(i);
0416:                        if ((ch != ' ') && (ch != '\t'))
0417:                            sb.append(ch);
0418:                    }
0419:                    value = sb.toString();
0420:                }
0421:
0422:                // Process each comma-delimited language specification
0423:                parser.setString(value); // ASSERT: parser is available to us
0424:                int length = parser.getLength();
0425:                while (true) {
0426:
0427:                    // Extract the next comma-delimited entry
0428:                    int start = parser.getIndex();
0429:                    if (start >= length)
0430:                        break;
0431:                    int end = parser.findChar(',');
0432:                    String entry = parser.extract(start, end).trim();
0433:                    parser.advance(); // For the following entry
0434:
0435:                    // Extract the quality factor for this entry
0436:                    double quality = 1.0;
0437:                    int semi = entry.indexOf(";q=");
0438:                    if (semi >= 0) {
0439:                        try {
0440:                            quality = Double.parseDouble(entry
0441:                                    .substring(semi + 3));
0442:                        } catch (NumberFormatException e) {
0443:                            quality = 0.0;
0444:                        }
0445:                        entry = entry.substring(0, semi);
0446:                    }
0447:
0448:                    // Skip entries we are not going to keep track of
0449:                    if (quality < 0.00005)
0450:                        continue; // Zero (or effectively zero) quality factors
0451:                    if ("*".equals(entry))
0452:                        continue; // FIXME - "*" entries are not handled
0453:
0454:                    // Extract the language and country for this entry
0455:                    String language = null;
0456:                    String country = null;
0457:                    String variant = null;
0458:                    int dash = entry.indexOf('-');
0459:                    if (dash < 0) {
0460:                        language = entry;
0461:                        country = "";
0462:                        variant = "";
0463:                    } else {
0464:                        language = entry.substring(0, dash);
0465:                        country = entry.substring(dash + 1);
0466:                        int vDash = country.indexOf('-');
0467:                        if (vDash > 0) {
0468:                            String cTemp = country.substring(0, vDash);
0469:                            variant = country.substring(vDash + 1);
0470:                            country = cTemp;
0471:                        } else {
0472:                            variant = "";
0473:                        }
0474:                    }
0475:
0476:                    // Add a new Locale to the list of Locales for this quality level
0477:                    Locale locale = new Locale(language, country, variant);
0478:                    Double key = new Double(-quality); // Reverse the order
0479:                    ArrayList values = (ArrayList) locales.get(key);
0480:                    if (values == null) {
0481:                        values = new ArrayList();
0482:                        locales.put(key, values);
0483:                    }
0484:                    values.add(locale);
0485:
0486:                }
0487:
0488:                // Process the quality values in highest->lowest order (due to
0489:                // negating the Double value when creating the key)
0490:                Iterator keys = locales.keySet().iterator();
0491:                while (keys.hasNext()) {
0492:                    Double key = (Double) keys.next();
0493:                    ArrayList list = (ArrayList) locales.get(key);
0494:                    Iterator values = list.iterator();
0495:                    while (values.hasNext()) {
0496:                        Locale locale = (Locale) values.next();
0497:                        if (debug >= 1)
0498:                            log(" Adding locale '" + locale + "'");
0499:                        request.addLocale(locale);
0500:                    }
0501:                }
0502:
0503:            }
0504:
0505:            /**
0506:             * Parse and record the connection parameters related to this request.
0507:             *
0508:             * @param socket The socket on which we are connected
0509:             *
0510:             * @exception IOException if an input/output error occurs
0511:             * @exception ServletException if a parsing error occurs
0512:             */
0513:            private void parseConnection(Socket socket) throws IOException,
0514:                    ServletException {
0515:
0516:                if (debug >= 2)
0517:                    log("  parseConnection: address=" + socket.getInetAddress()
0518:                            + ", port=" + connector.getPort());
0519:                ((HttpRequestImpl) request).setInet(socket.getInetAddress());
0520:                if (proxyPort != 0)
0521:                    request.setServerPort(proxyPort);
0522:                else
0523:                    request.setServerPort(serverPort);
0524:                request.setSocket(socket);
0525:
0526:            }
0527:
0528:            /**
0529:             * Parse the incoming HTTP request headers, and set the appropriate
0530:             * request headers.
0531:             *
0532:             * @param input The input stream connected to our socket
0533:             *
0534:             * @exception IOException if an input/output error occurs
0535:             * @exception ServletException if a parsing error occurs
0536:             */
0537:            private void parseHeaders(SocketInputStream input)
0538:                    throws IOException, ServletException {
0539:
0540:                while (true) {
0541:
0542:                    HttpHeader header = request.allocateHeader();
0543:
0544:                    // Read the next header
0545:                    input.readHeader(header);
0546:                    if (header.nameEnd == 0) {
0547:                        if (header.valueEnd == 0) {
0548:                            return;
0549:                        } else {
0550:                            throw new ServletException(
0551:                                    sm
0552:                                            .getString("httpProcessor.parseHeaders.colon"));
0553:                        }
0554:                    }
0555:
0556:                    String value = new String(header.value, 0, header.valueEnd);
0557:                    if (debug >= 1)
0558:                        log(" Header "
0559:                                + new String(header.name, 0, header.nameEnd)
0560:                                + " = " + value);
0561:
0562:                    // Set the corresponding request headers
0563:                    if (header.equals(DefaultHeaders.AUTHORIZATION_NAME)) {
0564:                        request.setAuthorization(value);
0565:                    } else if (header
0566:                            .equals(DefaultHeaders.ACCEPT_LANGUAGE_NAME)) {
0567:                        parseAcceptLanguage(value);
0568:                    } else if (header.equals(DefaultHeaders.COOKIE_NAME)) {
0569:                        Cookie cookies[] = RequestUtil.parseCookieHeader(value);
0570:                        for (int i = 0; i < cookies.length; i++) {
0571:                            if (cookies[i].getName().equals(
0572:                                    Globals.SESSION_COOKIE_NAME)) {
0573:                                // Override anything requested in the URL
0574:                                if (!request.isRequestedSessionIdFromCookie()) {
0575:                                    // Accept only the first session id cookie
0576:                                    request.setRequestedSessionId(cookies[i]
0577:                                            .getValue());
0578:                                    request.setRequestedSessionCookie(true);
0579:                                    request.setRequestedSessionURL(false);
0580:                                    if (debug >= 1)
0581:                                        log(" Requested cookie session id is "
0582:                                                + ((HttpServletRequest) request
0583:                                                        .getRequest())
0584:                                                        .getRequestedSessionId());
0585:                                }
0586:                            }
0587:                            if (debug >= 1)
0588:                                log(" Adding cookie " + cookies[i].getName()
0589:                                        + "=" + cookies[i].getValue());
0590:                            request.addCookie(cookies[i]);
0591:                        }
0592:                    } else if (header
0593:                            .equals(DefaultHeaders.CONTENT_LENGTH_NAME)) {
0594:                        int n = -1;
0595:                        try {
0596:                            n = Integer.parseInt(value);
0597:                        } catch (Exception e) {
0598:                            throw new ServletException(
0599:                                    sm
0600:                                            .getString("httpProcessor.parseHeaders.contentLength"));
0601:                        }
0602:                        request.setContentLength(n);
0603:                    } else if (header.equals(DefaultHeaders.CONTENT_TYPE_NAME)) {
0604:                        request.setContentType(value);
0605:                    } else if (header.equals(DefaultHeaders.HOST_NAME)) {
0606:                        int n = value.indexOf(':');
0607:                        if (n < 0) {
0608:                            if (connector.getScheme().equals("http")) {
0609:                                request.setServerPort(80);
0610:                            } else if (connector.getScheme().equals("https")) {
0611:                                request.setServerPort(443);
0612:                            }
0613:                            if (proxyName != null)
0614:                                request.setServerName(proxyName);
0615:                            else
0616:                                request.setServerName(value);
0617:                        } else {
0618:                            if (proxyName != null)
0619:                                request.setServerName(proxyName);
0620:                            else
0621:                                request.setServerName(value.substring(0, n)
0622:                                        .trim());
0623:                            if (proxyPort != 0)
0624:                                request.setServerPort(proxyPort);
0625:                            else {
0626:                                int port = 80;
0627:                                try {
0628:                                    port = Integer.parseInt(value.substring(
0629:                                            n + 1).trim());
0630:                                } catch (Exception e) {
0631:                                    throw new ServletException(
0632:                                            sm
0633:                                                    .getString("httpProcessor.parseHeaders.portNumber"));
0634:                                }
0635:                                request.setServerPort(port);
0636:                            }
0637:                        }
0638:                    } else if (header.equals(DefaultHeaders.CONNECTION_NAME)) {
0639:                        if (header
0640:                                .valueEquals(DefaultHeaders.CONNECTION_CLOSE_VALUE)) {
0641:                            keepAlive = false;
0642:                            response.setHeader("Connection", "close");
0643:                        }
0644:                        //request.setConnection(header);
0645:                        /*
0646:                          if ("keep-alive".equalsIgnoreCase(value)) {
0647:                          keepAlive = true;
0648:                          }
0649:                         */
0650:                    } else if (header.equals(DefaultHeaders.EXPECT_NAME)) {
0651:                        if (header.valueEquals(DefaultHeaders.EXPECT_100_VALUE))
0652:                            sendAck = true;
0653:                        else
0654:                            throw new ServletException(
0655:                                    sm
0656:                                            .getString("httpProcessor.parseHeaders.unknownExpectation"));
0657:                    } else if (header
0658:                            .equals(DefaultHeaders.TRANSFER_ENCODING_NAME)) {
0659:                        //request.setTransferEncoding(header);
0660:                    }
0661:
0662:                    request.nextHeader();
0663:
0664:                }
0665:
0666:            }
0667:
0668:            /**
0669:             * Parse the incoming HTTP request and set the corresponding HTTP request
0670:             * properties.
0671:             *
0672:             * @param input The input stream attached to our socket
0673:             * @param output The output stream of the socket
0674:             *
0675:             * @exception IOException if an input/output error occurs
0676:             * @exception ServletException if a parsing error occurs
0677:             */
0678:            private void parseRequest(SocketInputStream input,
0679:                    OutputStream output) throws IOException, ServletException {
0680:
0681:                // Parse the incoming request line
0682:                input.readRequestLine(requestLine);
0683:
0684:                // When the previous method returns, we're actually processing a 
0685:                // request
0686:                status = Constants.PROCESSOR_ACTIVE;
0687:
0688:                String method = new String(requestLine.method, 0,
0689:                        requestLine.methodEnd);
0690:                String uri = null;
0691:                String protocol = new String(requestLine.protocol, 0,
0692:                        requestLine.protocolEnd);
0693:
0694:                //System.out.println(" Method:" + method + "_ Uri:" + uri
0695:                //                   + "_ Protocol:" + protocol);
0696:
0697:                if (protocol.length() == 0)
0698:                    protocol = "HTTP/0.9";
0699:
0700:                // Now check if the connection should be kept alive after parsing the
0701:                // request.
0702:                if (protocol.equals("HTTP/1.1")) {
0703:                    http11 = true;
0704:                    sendAck = false;
0705:                } else {
0706:                    http11 = false;
0707:                    sendAck = false;
0708:                    // For HTTP/1.0, connection are not persistent by default,
0709:                    // unless specified with a Connection: Keep-Alive header.
0710:                    keepAlive = false;
0711:                }
0712:
0713:                // Validate the incoming request line
0714:                if (method.length() < 1) {
0715:                    throw new ServletException(sm
0716:                            .getString("httpProcessor.parseRequest.method"));
0717:                } else if (requestLine.uriEnd < 1) {
0718:                    throw new ServletException(sm
0719:                            .getString("httpProcessor.parseRequest.uri"));
0720:                }
0721:
0722:                // Parse any query parameters out of the request URI
0723:                int question = requestLine.indexOf("?");
0724:                if (question >= 0) {
0725:                    request.setQueryString(new String(requestLine.uri,
0726:                            question + 1, requestLine.uriEnd - question - 1));
0727:                    if (debug >= 1)
0728:                        log(" Query string is "
0729:                                + ((HttpServletRequest) request.getRequest())
0730:                                        .getQueryString());
0731:                    uri = new String(requestLine.uri, 0, question);
0732:                } else {
0733:                    request.setQueryString(null);
0734:                    uri = new String(requestLine.uri, 0, requestLine.uriEnd);
0735:                }
0736:
0737:                // Checking for an absolute URI (with the HTTP protocol)
0738:                if (!uri.startsWith("/")) {
0739:                    int pos = uri.indexOf("://");
0740:                    // Parsing out protocol and host name
0741:                    if (pos != -1) {
0742:                        pos = uri.indexOf('/', pos + 3);
0743:                        if (pos == -1) {
0744:                            uri = "";
0745:                        } else {
0746:                            uri = uri.substring(pos);
0747:                        }
0748:                    }
0749:                }
0750:
0751:                // Parse any requested session ID out of the request URI
0752:                int semicolon = uri.indexOf(match);
0753:                if (semicolon >= 0) {
0754:                    String rest = uri.substring(semicolon + match.length());
0755:                    int semicolon2 = rest.indexOf(';');
0756:                    if (semicolon2 >= 0) {
0757:                        request.setRequestedSessionId(rest.substring(0,
0758:                                semicolon2));
0759:                        rest = rest.substring(semicolon2);
0760:                    } else {
0761:                        request.setRequestedSessionId(rest);
0762:                        rest = "";
0763:                    }
0764:                    request.setRequestedSessionURL(true);
0765:                    uri = uri.substring(0, semicolon) + rest;
0766:                    if (debug >= 1)
0767:                        log(" Requested URL session id is "
0768:                                + ((HttpServletRequest) request.getRequest())
0769:                                        .getRequestedSessionId());
0770:                } else {
0771:                    request.setRequestedSessionId(null);
0772:                    request.setRequestedSessionURL(false);
0773:                }
0774:
0775:                // Normalize URI (using String operations at the moment)
0776:                String normalizedUri = normalize(uri);
0777:                if (debug >= 1)
0778:                    log("Normalized: '" + uri + "' to '" + normalizedUri + "'");
0779:
0780:                // Set the corresponding request properties
0781:                ((HttpRequest) request).setMethod(method);
0782:                request.setProtocol(protocol);
0783:                if (normalizedUri != null) {
0784:                    ((HttpRequest) request).setRequestURI(normalizedUri);
0785:                } else {
0786:                    ((HttpRequest) request).setRequestURI(uri);
0787:                }
0788:                request.setSecure(connector.getSecure());
0789:                request.setScheme(connector.getScheme());
0790:
0791:                if (normalizedUri == null) {
0792:                    log(" Invalid request URI: '" + uri + "'");
0793:                    throw new ServletException("Invalid URI: " + uri + "'");
0794:                }
0795:
0796:                if (debug >= 1)
0797:                    log(" Request is '" + method + "' for '" + uri
0798:                            + "' with protocol '" + protocol + "'");
0799:
0800:            }
0801:
0802:            /**
0803:             * Return a context-relative path, beginning with a "/", that represents
0804:             * the canonical version of the specified path after ".." and "." elements
0805:             * are resolved out.  If the specified path attempts to go outside the
0806:             * boundaries of the current context (i.e. too many ".." path elements
0807:             * are present), return <code>null</code> instead.
0808:             *
0809:             * @param path Path to be normalized
0810:             */
0811:            protected String normalize(String path) {
0812:
0813:                if (path == null)
0814:                    return null;
0815:
0816:                // Create a place for the normalized path
0817:                String normalized = path;
0818:
0819:                // Normalize "/%7E" and "/%7e" at the beginning to "/~"
0820:                if (normalized.startsWith("/%7E")
0821:                        || normalized.startsWith("/%7e"))
0822:                    normalized = "/~" + normalized.substring(4);
0823:
0824:                // Prevent encoding '%', '/', '.' and '\', which are special reserved
0825:                // characters
0826:                if ((normalized.indexOf("%25") >= 0)
0827:                        || (normalized.indexOf("%2F") >= 0)
0828:                        || (normalized.indexOf("%2E") >= 0)
0829:                        || (normalized.indexOf("%5C") >= 0)
0830:                        || (normalized.indexOf("%2f") >= 0)
0831:                        || (normalized.indexOf("%2e") >= 0)
0832:                        || (normalized.indexOf("%5c") >= 0)) {
0833:                    return null;
0834:                }
0835:
0836:                if (normalized.equals("/."))
0837:                    return "/";
0838:
0839:                // Normalize the slashes and add leading slash if necessary
0840:                if (normalized.indexOf('\\') >= 0)
0841:                    normalized = normalized.replace('\\', '/');
0842:                if (!normalized.startsWith("/"))
0843:                    normalized = "/" + normalized;
0844:
0845:                // Resolve occurrences of "//" in the normalized path
0846:                while (true) {
0847:                    int index = normalized.indexOf("//");
0848:                    if (index < 0)
0849:                        break;
0850:                    normalized = normalized.substring(0, index)
0851:                            + normalized.substring(index + 1);
0852:                }
0853:
0854:                // Resolve occurrences of "/./" in the normalized path
0855:                while (true) {
0856:                    int index = normalized.indexOf("/./");
0857:                    if (index < 0)
0858:                        break;
0859:                    normalized = normalized.substring(0, index)
0860:                            + normalized.substring(index + 2);
0861:                }
0862:
0863:                // Resolve occurrences of "/../" in the normalized path
0864:                while (true) {
0865:                    int index = normalized.indexOf("/../");
0866:                    if (index < 0)
0867:                        break;
0868:                    if (index == 0)
0869:                        return (null); // Trying to go outside our context
0870:                    int index2 = normalized.lastIndexOf('/', index - 1);
0871:                    normalized = normalized.substring(0, index2)
0872:                            + normalized.substring(index + 3);
0873:                }
0874:
0875:                // Declare occurrences of "/..." (three or more dots) to be invalid
0876:                // (on some Windows platforms this walks the directory tree!!!)
0877:                if (normalized.indexOf("/...") >= 0)
0878:                    return (null);
0879:
0880:                // Return the normalized path that we have completed
0881:                return (normalized);
0882:
0883:            }
0884:
0885:            /**
0886:             * Send a confirmation that a request has been processed when pipelining.
0887:             * HTTP/1.1 100 Continue is sent back to the client.
0888:             *
0889:             * @param output Socket output stream
0890:             */
0891:            private void ackRequest(OutputStream output) throws IOException {
0892:                if (sendAck)
0893:                    output.write(ack);
0894:            }
0895:
0896:            /**
0897:             * Process an incoming HTTP request on the Socket that has been assigned
0898:             * to this Processor.  Any exceptions that occur during processing must be
0899:             * swallowed and dealt with.
0900:             *
0901:             * @param socket The socket on which we are connected to the client
0902:             */
0903:            private void process(Socket socket) {
0904:
0905:                boolean ok = true;
0906:                boolean finishResponse = true;
0907:                SocketInputStream input = null;
0908:                OutputStream output = null;
0909:
0910:                // Construct and initialize the objects we will need
0911:                try {
0912:                    input = new SocketInputStream(socket.getInputStream(),
0913:                            connector.getBufferSize());
0914:                } catch (Exception e) {
0915:                    log("process.create", e);
0916:                    ok = false;
0917:                }
0918:
0919:                keepAlive = true;
0920:
0921:                while (!stopped && ok && keepAlive) {
0922:
0923:                    finishResponse = true;
0924:
0925:                    try {
0926:                        request.setStream(input);
0927:                        request.setResponse(response);
0928:                        output = socket.getOutputStream();
0929:                        response.setStream(output);
0930:                        response.setRequest(request);
0931:                        ((HttpServletResponse) response.getResponse())
0932:                                .setHeader("Server", SERVER_INFO);
0933:                    } catch (Exception e) {
0934:                        log("process.create", e);
0935:                        ok = false;
0936:                    }
0937:
0938:                    // Parse the incoming request
0939:                    try {
0940:                        if (ok) {
0941:                            parseConnection(socket);
0942:                            parseRequest(input, output);
0943:                            if (!request.getRequest().getProtocol().startsWith(
0944:                                    "HTTP/0"))
0945:                                parseHeaders(input);
0946:                            if (http11) {
0947:                                // Sending a request acknowledge back to the client if
0948:                                // requested.
0949:                                ackRequest(output);
0950:                                // If the protocol is HTTP/1.1, chunking is allowed.
0951:                                if (connector.isChunkingAllowed())
0952:                                    response.setAllowChunking(true);
0953:                            }
0954:                        }
0955:                    } catch (EOFException e) {
0956:                        // It's very likely to be a socket disconnect on either the 
0957:                        // client or the server
0958:                        ok = false;
0959:                        finishResponse = false;
0960:                    } catch (ServletException e) {
0961:                        ok = false;
0962:                        try {
0963:                            ((HttpServletResponse) response.getResponse())
0964:                                    .sendError(HttpServletResponse.SC_BAD_REQUEST);
0965:                        } catch (Exception f) {
0966:                            ;
0967:                        }
0968:                    } catch (InterruptedIOException e) {
0969:                        if (debug > 1) {
0970:                            try {
0971:                                log("process.parse", e);
0972:                                ((HttpServletResponse) response.getResponse())
0973:                                        .sendError(HttpServletResponse.SC_BAD_REQUEST);
0974:                            } catch (Exception f) {
0975:                                ;
0976:                            }
0977:                        }
0978:                        ok = false;
0979:                    } catch (Exception e) {
0980:                        try {
0981:                            log("process.parse", e);
0982:                            ((HttpServletResponse) response.getResponse())
0983:                                    .sendError(HttpServletResponse.SC_BAD_REQUEST);
0984:                        } catch (Exception f) {
0985:                            ;
0986:                        }
0987:                        ok = false;
0988:                    }
0989:
0990:                    // Ask our Container to process this request
0991:                    try {
0992:                        ((HttpServletResponse) response).setHeader("Date",
0993:                                FastHttpDateFormat.getCurrentDate());
0994:                        if (ok) {
0995:                            connector.getContainer().invoke(request, response);
0996:                        }
0997:                    } catch (ServletException e) {
0998:                        log("process.invoke", e);
0999:                        try {
1000:                            ((HttpServletResponse) response.getResponse())
1001:                                    .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
1002:                        } catch (Exception f) {
1003:                            ;
1004:                        }
1005:                        ok = false;
1006:                    } catch (InterruptedIOException e) {
1007:                        ok = false;
1008:                    } catch (Throwable e) {
1009:                        log("process.invoke", e);
1010:                        try {
1011:                            ((HttpServletResponse) response.getResponse())
1012:                                    .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
1013:                        } catch (Exception f) {
1014:                            ;
1015:                        }
1016:                        ok = false;
1017:                    }
1018:
1019:                    // Finish up the handling of the request
1020:                    if (finishResponse) {
1021:                        try {
1022:                            response.finishResponse();
1023:                        } catch (IOException e) {
1024:                            ok = false;
1025:                        } catch (Throwable e) {
1026:                            log("process.invoke", e);
1027:                            ok = false;
1028:                        }
1029:                        try {
1030:                            request.finishRequest();
1031:                        } catch (IOException e) {
1032:                            ok = false;
1033:                        } catch (Throwable e) {
1034:                            log("process.invoke", e);
1035:                            ok = false;
1036:                        }
1037:                        try {
1038:                            if (output != null)
1039:                                output.flush();
1040:                        } catch (IOException e) {
1041:                            ok = false;
1042:                        }
1043:                    }
1044:
1045:                    // We have to check if the connection closure has been requested
1046:                    // by the application or the response stream (in case of HTTP/1.0
1047:                    // and keep-alive).
1048:                    if ("close".equals(response.getHeader("Connection"))) {
1049:                        keepAlive = false;
1050:                    }
1051:
1052:                    // End of request processing
1053:                    status = Constants.PROCESSOR_IDLE;
1054:
1055:                    // Recycling the request and the response objects
1056:                    request.recycle();
1057:                    response.recycle();
1058:
1059:                }
1060:
1061:                try {
1062:                    shutdownInput(input);
1063:                    socket.close();
1064:                } catch (IOException e) {
1065:                    ;
1066:                } catch (Throwable e) {
1067:                    log("process.invoke", e);
1068:                }
1069:                socket = null;
1070:
1071:            }
1072:
1073:            protected void shutdownInput(InputStream input) {
1074:                try {
1075:                    int available = input.available();
1076:                    // skip any unread (bogus) bytes
1077:                    if (available > 0) {
1078:                        input.skip(available);
1079:                    }
1080:                } catch (Throwable e) {
1081:                    ;
1082:                }
1083:            }
1084:
1085:            // ---------------------------------------------- Background Thread Methods
1086:
1087:            /**
1088:             * The background thread that listens for incoming TCP/IP connections and
1089:             * hands them off to an appropriate processor.
1090:             */
1091:            public void run() {
1092:
1093:                // Process requests until we receive a shutdown signal
1094:                while (!stopped) {
1095:
1096:                    // Wait for the next socket to be assigned
1097:                    Socket socket = await();
1098:                    if (socket == null)
1099:                        continue;
1100:
1101:                    // Process the request from this socket
1102:                    try {
1103:                        process(socket);
1104:                    } catch (Throwable t) {
1105:                        log("process.invoke", t);
1106:                    }
1107:
1108:                    // Finish up this request
1109:                    connector.recycle(this );
1110:
1111:                }
1112:
1113:                // Tell threadStop() we have shut ourselves down successfully
1114:                synchronized (threadSync) {
1115:                    threadSync.notifyAll();
1116:                }
1117:
1118:            }
1119:
1120:            /**
1121:             * Start the background processing thread.
1122:             */
1123:            private void threadStart() {
1124:
1125:                log(sm.getString("httpProcessor.starting"));
1126:
1127:                thread = new Thread(this , threadName);
1128:                thread.setDaemon(true);
1129:                thread.start();
1130:
1131:                if (debug >= 1)
1132:                    log(" Background thread has been started");
1133:
1134:            }
1135:
1136:            /**
1137:             * Stop the background processing thread.
1138:             */
1139:            private void threadStop() {
1140:
1141:                log(sm.getString("httpProcessor.stopping"));
1142:
1143:                stopped = true;
1144:                assign(null);
1145:
1146:                if (status != Constants.PROCESSOR_IDLE) {
1147:                    // Only wait if the processor is actually processing a command
1148:                    synchronized (threadSync) {
1149:                        try {
1150:                            threadSync.wait(5000);
1151:                        } catch (InterruptedException e) {
1152:                            ;
1153:                        }
1154:                    }
1155:                }
1156:                thread = null;
1157:
1158:            }
1159:
1160:            // ------------------------------------------------------ Lifecycle Methods
1161:
1162:            /**
1163:             * Add a lifecycle event listener to this component.
1164:             *
1165:             * @param listener The listener to add
1166:             */
1167:            public void addLifecycleListener(LifecycleListener listener) {
1168:
1169:                lifecycle.addLifecycleListener(listener);
1170:
1171:            }
1172:
1173:            /**
1174:             * Get the lifecycle listeners associated with this lifecycle. If this 
1175:             * Lifecycle has no listeners registered, a zero-length array is returned.
1176:             */
1177:            public LifecycleListener[] findLifecycleListeners() {
1178:
1179:                return lifecycle.findLifecycleListeners();
1180:
1181:            }
1182:
1183:            /**
1184:             * Remove a lifecycle event listener from this component.
1185:             *
1186:             * @param listener The listener to add
1187:             */
1188:            public void removeLifecycleListener(LifecycleListener listener) {
1189:
1190:                lifecycle.removeLifecycleListener(listener);
1191:
1192:            }
1193:
1194:            /**
1195:             * Start the background thread we will use for request processing.
1196:             *
1197:             * @exception LifecycleException if a fatal startup error occurs
1198:             */
1199:            public void start() throws LifecycleException {
1200:
1201:                if (started)
1202:                    throw new LifecycleException(sm
1203:                            .getString("httpProcessor.alreadyStarted"));
1204:                lifecycle.fireLifecycleEvent(START_EVENT, null);
1205:                started = true;
1206:
1207:                threadStart();
1208:
1209:            }
1210:
1211:            /**
1212:             * Stop the background thread we will use for request processing.
1213:             *
1214:             * @exception LifecycleException if a fatal shutdown error occurs
1215:             */
1216:            public void stop() throws LifecycleException {
1217:
1218:                if (!started)
1219:                    throw new LifecycleException(sm
1220:                            .getString("httpProcessor.notStarted"));
1221:                lifecycle.fireLifecycleEvent(STOP_EVENT, null);
1222:                started = false;
1223:
1224:                threadStop();
1225:
1226:            }
1227:
1228:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.