5. Araxis Merge File Comparison Report

Produced by Araxis Merge on 2016-08-05 09:21:31 +0000. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.

5.1 Files compared

#LocationFileLast Modified
1/Merge Test Files/jakarta-tomcat-4.0.6-src/catalina/src/share/org/apache/catalina/connector/httpHttpProcessor.java2002-10-08 14:15:34 +0000
2/Merge Test Files/jakarta-tomcat-4.1.18-src/catalina/src/share/org/apache/catalina/connector/httpHttpProcessor.java2002-12-19 13:49:42 +0000
3/Merge Test Files/jakarta-tomcat-4.1.24-src/catalina/src/share/org/apache/catalina/connector/httpHttpProcessor.java2003-03-19 09:18:36 +0000
Note: Merge considers the second file to be the common ancestor of the others.

5.2 Comparison summary

DescriptionBetween
Files 1 and 2
Between
Files 2 and 3
Relative to
Common Ancestor
Text BlocksLinesText BlocksLinesText BlocksLines
Unchanged17246012570
Changed92800928
Inserted7410014
Removed1400741
Note: An automatic merge would leave 0 conflict(s).

5.3 Comparison options

WhitespaceDifferences in whitespace are significant
Character caseDifferences in character case are significant
Line endingsDifferences in line endings (CR and LF characters) are significant
CR/LF charactersNot shown in the comparison detail

5.4 Active regular expressions

No regular expressions were active.

5.5 Comparison detail

1 /* * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http/HttpProcessor.java,v 1.36.2.5 2002/04/04 17:46:08 remm Exp $ 1 /* * $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 $
 1 /* * $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 $
2  * $Revision: 1.36.2.5 $ 2  * $Revision: 1.46
 $
 2  * $Revision: 1.46 $
3  * $Date: 2002/04/04 17:46:08 $ 3  * $Date: 2002/04/04 17:50:34 $ 3  * $Date: 2002/04/04 17:50:34 $
4  * 4  * 4  *
5  * ==================================================================== 5  * ==================================================================== 5  * ====================================================================
6  * 6  * 6  *
7  * The Apache Software License, Version 1.1 7  * The Apache Software License, Version 1.1 7  * The Apache Software License, Version 1.1
8  * 8  * 8  *
9  * Copyright (c) 1999 The Apache Software Foundation.  All rights 9  * Copyright (c) 1999 The Apache Software Foundation.  All rights 9  * Copyright (c) 1999 The Apache Software Foundation.  All rights
10  * reserved. 10  * reserved. 10  * reserved.
11  * 11  * 11  *
12  * Redistribution and use in source and binary forms, with or without 12  * Redistribution and use in source and binary forms, with or without 12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions 13  * modification, are permitted provided that the following conditions 13  * modification, are permitted provided that the following conditions
14  * are met: 14  * are met: 14  * are met:
15  * 15  * 15  *
16  * 1. Redistributions of source code must retain the above copyright 16  * 1. Redistributions of source code must retain the above copyright 16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer. 17  *    notice, this list of conditions and the following disclaimer. 17  *    notice, this list of conditions and the following disclaimer.
18  * 18  * 18  *
19  * 2. Redistributions in binary form must reproduce the above copyright 19  * 2. Redistributions in binary form must reproduce the above copyright 19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in 20  *    notice, this list of conditions and the following disclaimer in 20  *    notice, this list of conditions and the following disclaimer in
21  *    the documentation and/or other materials provided with the 21  *    the documentation and/or other materials provided with the 21  *    the documentation and/or other materials provided with the
22  *    distribution. 22  *    distribution. 22  *    distribution.
23  * 23  * 23  *
24  * 3. The end-user documentation included with the redistribution, if 24  * 3. The end-user documentation included with the redistribution, if 24  * 3. The end-user documentation included with the redistribution, if
25  *    any, must include the following acknowlegement: 25  *    any, must include the following acknowlegement: 25  *    any, must include the following acknowlegement:
26  *       "This product includes software developed by the 26  *       "This product includes software developed by the 26  *       "This product includes software developed by the
27  *        Apache Software Foundation (http://www.apache.org/)." 27  *        Apache Software Foundation (http://www.apache.org/)." 27  *        Apache Software Foundation (http://www.apache.org/)."
28  *    Alternately, this acknowlegement may appear in the software itself, 28  *    Alternately, this acknowlegement may appear in the software itself, 28  *    Alternately, this acknowlegement may appear in the software itself,
29  *    if and wherever such third-party acknowlegements normally appear. 29  *    if and wherever such third-party acknowlegements normally appear. 29  *    if and wherever such third-party acknowlegements normally appear.
30  * 30  * 30  *
31  * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software 31  * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software 31  * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
32  *    Foundation" must not be used to endorse or promote products derived 32  *    Foundation" must not be used to endorse or promote products derived 32  *    Foundation" must not be used to endorse or promote products derived
33  *    from this software without prior written permission. For written 33  *    from this software without prior written permission. For written 33  *    from this software without prior written permission. For written
34  *    permission, please contact apache@apache.org. 34  *    permission, please contact apache@apache.org. 34  *    permission, please contact apache@apache.org.
35  * 35  * 35  *
36  * 5. Products derived from this software may not be called "Apache" 36  * 5. Products derived from this software may not be called "Apache" 36  * 5. Products derived from this software may not be called "Apache"
37  *    nor may "Apache" appear in their names without prior written 37  *    nor may "Apache" appear in their names without prior written 37  *    nor may "Apache" appear in their names without prior written
38  *    permission of the Apache Group. 38  *    permission of the Apache Group. 38  *    permission of the Apache Group.
39  * 39  * 39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 43  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 43  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 46  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 46  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE. 51  * SUCH DAMAGE. 51  * SUCH DAMAGE.
52  * ==================================================================== 52  * ==================================================================== 52  * ====================================================================
53  * 53  * 53  *
54  * This software consists of voluntary contributions made by many 54  * This software consists of voluntary contributions made by many 54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Apache Software Foundation.  For more 55  * individuals on behalf of the Apache Software Foundation.  For more 55  * individuals on behalf of the Apache Software Foundation.  For more
56  * information on the Apache Software Foundation, please see 56  * information on the Apache Software Foundation, please see 56  * information on the Apache Software Foundation, please see
57  * <http://www.apache.org/>. 57  * <http://www.apache.org/>. 57  * <http://www.apache.org/>.
58  * 58  * 58  *
59  * [Additional notices, if required by prior licensing conditions] 59  * [Additional notices, if required by prior licensing conditions] 59  * [Additional notices, if required by prior licensing conditions]
60  * 60  * 60  *
61  */ 61  */ 61  */
62  62  62 
63  63  63 
64 package org.apache.catalina.connector.http; 64 package org.apache.catalina.connector.http; 64 package org.apache.catalina.connector.http;
65  65  65 
66  66  66 
67 import java.io.BufferedInputStream; 67 import java.io.BufferedInputStream; 67 import java.io.BufferedInputStream;
68 import java.io.EOFException; 68 import java.io.EOFException; 68 import java.io.EOFException;
69 import java.io.InterruptedIOException; 69 import java.io.InterruptedIOException; 69 import java.io.InterruptedIOException;
70 import java.io.InputStream; 70 import java.io.InputStream; 70 import java.io.InputStream;
71 import java.io.IOException; 71 import java.io.IOException; 71 import java.io.IOException;
72 import java.io.OutputStream; 72 import java.io.OutputStream; 72 import java.io.OutputStream;
73 import java.net.InetAddress; 73 import java.net.InetAddress; 73 import java.net.InetAddress;
74 import java.net.Socket; 74 import java.net.Socket; 74 import java.net.Socket;
75 import java.util.ArrayList; 75 import java.util.ArrayList; 75 import java.util.ArrayList;
76 import java.util.Iterator; 76 import java.util.Iterator; 76 import java.util.Iterator;
77 import java.util.Locale; 77 import java.util.Locale; 77 import java.util.Locale;
78 import java.util.StringTokenizer; 78 import java.util.StringTokenizer; 78 import java.util.StringTokenizer;
79 import java.util.TreeMap; 79 import java.util.TreeMap; 79 import java.util.TreeMap;
80 import javax.servlet.ServletException; 80 import javax.servlet.ServletException; 80 import javax.servlet.ServletException;
81 import javax.servlet.http.Cookie; 81 import javax.servlet.http.Cookie; 81 import javax.servlet.http.Cookie;
82 import javax.servlet.http.HttpServletRequest; 82 import javax.servlet.http.HttpServletRequest; 82 import javax.servlet.http.HttpServletRequest;
83 import javax.servlet.http.HttpServletResponse; 83 import javax.servlet.http.HttpServletResponse; 83 import javax.servlet.http.HttpServletResponse;
84 import org.apache.catalina.Connector; 84 import org.apache.catalina.Connector; 84 import org.apache.catalina.Connector;
85 import org.apache.catalina.Container; 85 import org.apache.catalina.Container; 85 import org.apache.catalina.Container;
86 import org.apache.catalina.Globals; 86 import org.apache.catalina.Globals; 86 import org.apache.catalina.Globals;
87 import org.apache.catalina.HttpRequest; 87 import org.apache.catalina.HttpRequest; 87 import org.apache.catalina.HttpRequest;
88 import org.apache.catalina.HttpResponse; 88 import org.apache.catalina.HttpResponse; 88 import org.apache.catalina.HttpResponse;
89 import org.apache.catalina.Lifecycle; 89 import org.apache.catalina.Lifecycle; 89 import org.apache.catalina.Lifecycle;
90 import org.apache.catalina.LifecycleEvent; 90 import org.apache.catalina.LifecycleEvent; 90 import org.apache.catalina.LifecycleEvent;
91 import org.apache.catalina.LifecycleException; 91 import org.apache.catalina.LifecycleException; 91 import org.apache.catalina.LifecycleException;
92 import org.apache.catalina.LifecycleListener; 92 import org.apache.catalina.LifecycleListener; 92 import org.apache.catalina.LifecycleListener;
93 import org.apache.catalina.Logger; 93 import org.apache.catalina.Logger; 93 import org.apache.catalina.Logger;
94 import org.apache.catalina.util.RequestUtil; 94 import org.apache.catalina.util.FastHttpDateFormat
;
 94 import org.apache.catalina.util.FastHttpDateFormat;
95 import org.apache.catalina.util.LifecycleSupport; 95 import org.apache.catalina.util.LifecycleSupport; 95 import org.apache.catalina.util.LifecycleSupport;
    96 import org.apache.catalina.util.RequestUtil; 96 import org.apache.catalina.util.RequestUtil;
    97 import org.apache.catalina.util.ServerInfo; 97 import org.apache.catalina.util.ServerInfo;
96 import org.apache.catalina.util.StringManager; 98 import org.apache.catalina.util.StringManager; 98 import org.apache.catalina.util.StringManager;
97 import org.apache.catalina.util.StringParser; 99 import org.apache.catalina.util.StringParser; 99 import org.apache.catalina.util.StringParser;
98  100  100 
99  101  101 
100 /** 102 /** 102 /**
101  * Implementation of a request processor (and its associated thread) that may 103  * Implementation of a request processor (and its associated thread) that may 103  * Implementation of a request processor (and its associated thread) that may
102  * be used by an HttpConnector to process individual requests.  The connector 104  * be used by an HttpConnector to process individual requests.  The connector 104  * be used by an HttpConnector to process individual requests.  The connector
103  * will allocate a processor from its pool, assign a particular socket to it, 105  * will allocate a processor from its pool, assign a particular socket to it, 105  * will allocate a processor from its pool, assign a particular socket to it,
104  * and the processor will then execute the processing required to complete 106  * and the processor will then execute the processing required to complete 106  * and the processor will then execute the processing required to complete
105  * the request.  When the processor is completed, it will recycle itself. 107  * the request.  When the processor is completed, it will recycle itself. 107  * the request.  When the processor is completed, it will recycle itself.
106  * 108  * 108  *
107  * @author Craig R. McClanahan 109  * @author Craig R. McClanahan 109  * @author Craig R. McClanahan
108  * @author Remy Maucherat 110  * @author Remy Maucherat 110  * @author Remy Maucherat
109  * @version $Revision: 1.36.2.5 $ $Date: 2002/04/04 17:46:08 $ 111  * @version $Revision: 1.46
 $ $Date: 2002/04/04 17:50:34 $
 111  * @version $Revision: 1.46 $ $Date: 2002/04/04 17:50:34 $
    112  * @deprecated 112  * @deprecated
110  */ 113  */ 113  */
111  114  114 
112 final class HttpProcessor 115 final class HttpProcessor 115 final class HttpProcessor
113     implements Lifecycle, Runnable { 116     implements Lifecycle, Runnable { 116     implements Lifecycle, Runnable {
114  117  117 
115  118  118 
    119     // ----------------------------------------------------- Manifest Constants 119     // ----------------------------------------------------- Manifest Constants
    120  120 
    121  121 
    122     /** 122     /**
    123      * Server information string for this server. 123      * Server information string for this server.
    124      */ 124      */
    125     private static final String SERVER_INFO = 125     private static final String SERVER_INFO =
    126         ServerInfo.getServerInfo() + " (HTTP/1.1 Connector)"; 126         ServerInfo.getServerInfo() + " (HTTP/1.1 Connector)";
    127  127 
    128  128 
116     // ----------------------------------------------------------- Constructors 129     // ----------------------------------------------------------- Constructors 129     // ----------------------------------------------------------- Constructors
117  130  130 
118  131  131 
119     /** 132     /** 132     /**
120      * Construct a new HttpProcessor associated with the specified connector. 133      * Construct a new HttpProcessor associated with the specified connector. 133      * Construct a new HttpProcessor associated with the specified connector.
121      * 134      * 134      *
122      * @param connector HttpConnector that owns this processor 135      * @param connector HttpConnector that owns this processor 135      * @param connector HttpConnector that owns this processor
123      * @param id Identifier of this HttpProcessor (unique per connector) 136      * @param id Identifier of this HttpProcessor (unique per connector) 136      * @param id Identifier of this HttpProcessor (unique per connector)
124      */ 137      */ 137      */
125     public HttpProcessor(HttpConnector connector, int id) { 138     public HttpProcessor(HttpConnector connector, int id) { 138     public HttpProcessor(HttpConnector connector, int id) {
126  139  139 
127         super(); 140         super(); 140         super();
128         this.connector = connector; 141         this.connector = connector; 141         this.connector = connector;
129         this.debug = connector.getDebug(); 142         this.debug = connector.getDebug(); 142         this.debug = connector.getDebug();
130         this.id = id; 143         this.id = id; 143         this.id = id;
131         this.proxyName = connector.getProxyName(); 144         this.proxyName = connector.getProxyName(); 144         this.proxyName = connector.getProxyName();
132         this.proxyPort = connector.getProxyPort(); 145         this.proxyPort = connector.getProxyPort(); 145         this.proxyPort = connector.getProxyPort();
133         this.request = (HttpRequestImpl) connector.createRequest(); 146         this.request = (HttpRequestImpl) connector.createRequest(); 146         this.request = (HttpRequestImpl) connector.createRequest();
134         this.response = (HttpResponseImpl) connector.createResponse(); 147         this.response = (HttpResponseImpl) connector.createResponse(); 147         this.response = (HttpResponseImpl) connector.createResponse();
135         this.serverPort = connector.getPort(); 148         this.serverPort = connector.getPort(); 148         this.serverPort = connector.getPort();
136         this.threadName = 149         this.threadName = 149         this.threadName =
137           "HttpProcessor[" + connector.getPort() + "][" + id + "]"; 150           "HttpProcessor[" + connector.getPort() + "][" + id + "]"; 150           "HttpProcessor[" + connector.getPort() + "][" + id + "]";
138  151  151 
139     } 152     } 152     }
140  153  153 
141  154  154 
142     // ----------------------------------------------------- Instance Variables 155     // ----------------------------------------------------- Instance Variables 155     // ----------------------------------------------------- Instance Variables
143  156  156 
144  157  157 
145     /** 158     /** 158     /**
146      * Is there a new socket available? 159      * Is there a new socket available? 159      * Is there a new socket available?
147      */ 160      */ 160      */
148     private boolean available = false; 161     private boolean available = false; 161     private boolean available = false;
149  162  162 
150  163  163 
151     /** 164     /** 164     /**
152      * The HttpConnector with which this processor is associated. 165      * The HttpConnector with which this processor is associated. 165      * The HttpConnector with which this processor is associated.
153      */ 166      */ 166      */
154     private HttpConnector connector = null; 167     private HttpConnector connector = null; 167     private HttpConnector connector = null;
155  168  168 
156  169  169 
157     /** 170     /** 170     /**
158      * The debugging detail level for this component. 171      * The debugging detail level for this component. 171      * The debugging detail level for this component.
159      */ 172      */ 172      */
160     private int debug = 0; 173     private int debug = 0; 173     private int debug = 0;
161  174  174 
162  175  175 
163     /** 176     /** 176     /**
164      * The identifier of this processor, unique per connector. 177      * The identifier of this processor, unique per connector. 177      * The identifier of this processor, unique per connector.
165      */ 178      */ 178      */
166     private int id = 0; 179     private int id = 0; 179     private int id = 0;
167  180  180 
168  181  181 
169     /** 182     /** 182     /**
170      * The lifecycle event support for this component. 183      * The lifecycle event support for this component. 183      * The lifecycle event support for this component.
171      */ 184      */ 184      */
172     private LifecycleSupport lifecycle = new LifecycleSupport(this); 185     private LifecycleSupport lifecycle = new LifecycleSupport(this); 185     private LifecycleSupport lifecycle = new LifecycleSupport(this);
173  186  186 
174  187  187 
175     /** 188     /** 188     /**
176      * The match string for identifying a session ID parameter. 189      * The match string for identifying a session ID parameter. 189      * The match string for identifying a session ID parameter.
177      */ 190      */ 190      */
178     private static final String match = 191     private static final String match = 191     private static final String match =
179         ";" + Globals.SESSION_PARAMETER_NAME + "="; 192         ";" + Globals.SESSION_PARAMETER_NAME + "="; 192         ";" + Globals.SESSION_PARAMETER_NAME + "=";
180  193  193 
181  194  194 
182     /** 195     /** 195     /**
183      * The match string for identifying a session ID parameter. 196      * The match string for identifying a session ID parameter. 196      * The match string for identifying a session ID parameter.
184      */ 197      */ 197      */
185     private static final char[] SESSION_ID = match.toCharArray(); 198     private static final char[] SESSION_ID = match.toCharArray(); 198     private static final char[] SESSION_ID = match.toCharArray();
186  199  199 
187  200  200 
188     /** 201     /** 201     /**
189      * The string parser we will use for parsing request lines. 202      * The string parser we will use for parsing request lines. 202      * The string parser we will use for parsing request lines.
190      */ 203      */ 203      */
191     private StringParser parser = new StringParser(); 204     private StringParser parser = new StringParser(); 204     private StringParser parser = new StringParser();
192  205  205 
193  206  206 
194     /** 207     /** 207     /**
195      * The proxy server name for our Connector. 208      * The proxy server name for our Connector. 208      * The proxy server name for our Connector.
196      */ 209      */ 209      */
197     private String proxyName = null; 210     private String proxyName = null; 210     private String proxyName = null;
198  211  211 
199  212  212 
200     /** 213     /** 213     /**
201      * The proxy server port for our Connector. 214      * The proxy server port for our Connector. 214      * The proxy server port for our Connector.
202      */ 215      */ 215      */
203     private int proxyPort = 0; 216     private int proxyPort = 0; 216     private int proxyPort = 0;
204  217  217 
205  218  218 
206     /** 219     /** 219     /**
207      * The HTTP request object we will pass to our associated container. 220      * The HTTP request object we will pass to our associated container. 220      * The HTTP request object we will pass to our associated container.
208      */ 221      */ 221      */
209     private HttpRequestImpl request = null; 222     private HttpRequestImpl request = null; 222     private HttpRequestImpl request = null;
210  223  223 
211  224  224 
212     /** 225     /** 225     /**
213      * The HTTP response object we will pass to our associated container. 226      * The HTTP response object we will pass to our associated container. 226      * The HTTP response object we will pass to our associated container.
214      */ 227      */ 227      */
215     private HttpResponseImpl response = null; 228     private HttpResponseImpl response = null; 228     private HttpResponseImpl response = null;
216  229  229 
217  230  230 
218     /** 231     /** 231     /**
219      * The actual server port for our Connector. 232      * The actual server port for our Connector. 232      * The actual server port for our Connector.
220      */ 233      */ 233      */
221     private int serverPort = 0; 234     private int serverPort = 0; 234     private int serverPort = 0;
222  235  235 
223  236  236 
224     /** 237     /** 237     /**
225      * The string manager for this package. 238      * The string manager for this package. 238      * The string manager for this package.
226      */ 239      */ 239      */
227     protected StringManager sm = 240     protected StringManager sm = 240     protected StringManager sm =
228         StringManager.getManager(Constants.Package); 241         StringManager.getManager(Constants.Package); 241         StringManager.getManager(Constants.Package);
229  242  242 
230  243  243 
231     /** 244     /** 244     /**
232      * The socket we are currently processing a request for.  This object 245      * The socket we are currently processing a request for.  This object 245      * The socket we are currently processing a request for.  This object
233      * is used for inter-thread communication only. 246      * is used for inter-thread communication only. 246      * is used for inter-thread communication only.
234      */ 247      */ 247      */
235     private Socket socket = null; 248     private Socket socket = null; 248     private Socket socket = null;
236  249  249 
237  250  250 
238     /** 251     /** 251     /**
239      * Has this component been started yet? 252      * Has this component been started yet? 252      * Has this component been started yet?
240      */ 253      */ 253      */
241     private boolean started = false; 254     private boolean started = false; 254     private boolean started = false;
242  255  255 
243  256  256 
244     /** 257     /** 257     /**
245      * The shutdown signal to our background thread 258      * The shutdown signal to our background thread 258      * The shutdown signal to our background thread
246      */ 259      */ 259      */
247     private boolean stopped = false; 260     private boolean stopped = false; 260     private boolean stopped = false;
248  261  261 
249  262  262 
250     /** 263     /** 263     /**
251      * The background thread. 264      * The background thread. 264      * The background thread.
252      */ 265      */ 265      */
253     private Thread thread = null; 266     private Thread thread = null; 266     private Thread thread = null;
254  267  267 
255  268  268 
256     /** 269     /** 269     /**
257      * The name to register for the background thread. 270      * The name to register for the background thread. 270      * The name to register for the background thread.
258      */ 271      */ 271      */
259     private String threadName = null; 272     private String threadName = null; 272     private String threadName = null;
260  273  273 
261  274  274 
262     /** 275     /** 275     /**
263      * The thread synchronization object. 276      * The thread synchronization object. 276      * The thread synchronization object.
264      */ 277      */ 277      */
265     private Object threadSync = new Object(); 278     private Object threadSync = new Object(); 278     private Object threadSync = new Object();
266  279  279 
267  280  280 
268     /** 281     /** 281     /**
269      * Keep alive indicator. 282      * Keep alive indicator. 282      * Keep alive indicator.
270      */ 283      */ 283      */
271     private boolean keepAlive = false; 284     private boolean keepAlive = false; 284     private boolean keepAlive = false;
272  285  285 
273  286  286 
274     /** 287     /** 287     /**
275      * HTTP/1.1 client. 288      * HTTP/1.1 client. 288      * HTTP/1.1 client.
276      */ 289      */ 289      */
277     private boolean http11 = true; 290     private boolean http11 = true; 290     private boolean http11 = true;
278  291  291 
279  292  292 
280     /** 293     /** 293     /**
281      * True if the client has asked to recieve a request acknoledgement. If so 294      * True if the client has asked to recieve a request acknoledgement. If so 294      * True if the client has asked to recieve a request acknoledgement. If so
282      * the server will send a preliminary 100 Continue response just after it 295      * the server will send a preliminary 100 Continue response just after it 295      * the server will send a preliminary 100 Continue response just after it
283      * has successfully parsed the request headers, and before starting 296      * has successfully parsed the request headers, and before starting 296      * has successfully parsed the request headers, and before starting
284      * reading the request entity body. 297      * reading the request entity body. 297      * reading the request entity body.
285      */ 298      */ 298      */
286     private boolean sendAck = false; 299     private boolean sendAck = false; 299     private boolean sendAck = false;
287  300  300 
288  301  301 
289     /** 302     /** 302     /**
290      * Ack string when pipelining HTTP requests. 303      * Ack string when pipelining HTTP requests. 303      * Ack string when pipelining HTTP requests.
291      */ 304      */ 304      */
292     private static final byte[] ack = 305     private static final byte[] ack = 305     private static final byte[] ack =
293         (new String("HTTP/1.1 100 Continue\r\n\r\n")).getBytes(); 306         (new String("HTTP/1.1 100 Continue\r\n\r\n")).getBytes(); 306         (new String("HTTP/1.1 100 Continue\r\n\r\n")).getBytes();
294  307  307 
295  308  308 
296     /** 309     /** 309     /**
297      * CRLF. 310      * CRLF. 310      * CRLF.
298      */ 311      */ 311      */
299     private static final byte[] CRLF = (new String("\r\n")).getBytes(); 312     private static final byte[] CRLF = (new String("\r\n")).getBytes(); 312     private static final byte[] CRLF = (new String("\r\n")).getBytes();
300  313  313 
301  314  314 
302     /** 315     /** 315     /**
303      * Line buffer. 316      * Line buffer. 316      * Line buffer.
304      */ 317      */ 317      */
305     //private char[] lineBuffer = new char[4096]; 318     //private char[] lineBuffer = new char[4096]; 318     //private char[] lineBuffer = new char[4096];
306  319  319 
307  320  320 
308     /** 321     /** 321     /**
309      * Request line buffer. 322      * Request line buffer. 322      * Request line buffer.
310      */ 323      */ 323      */
311     private HttpRequestLine requestLine = new HttpRequestLine(); 324     private HttpRequestLine requestLine = new HttpRequestLine(); 324     private HttpRequestLine requestLine = new HttpRequestLine();
312  325  325 
313  326  326 
314     /** 327     /** 327     /**
315      * Processor state 328      * Processor state 328      * Processor state
316      */ 329      */ 329      */
317     private int status = Constants.PROCESSOR_IDLE; 330     private int status = Constants.PROCESSOR_IDLE; 330     private int status = Constants.PROCESSOR_IDLE;
318  331  331 
319  332  332 
320     // --------------------------------------------------------- Public Methods 333     // --------------------------------------------------------- Public Methods 333     // --------------------------------------------------------- Public Methods
321  334  334 
322  335  335 
323     /** 336     /** 336     /**
324      * Return a String value representing this object. 337      * Return a String value representing this object. 337      * Return a String value representing this object.
325      */ 338      */ 338      */
326     public String toString() { 339     public String toString() { 339     public String toString() {
327  340  340 
328         return (this.threadName); 341         return (this.threadName); 341         return (this.threadName);
329  342  342 
330     } 343     } 343     }
331  344  344 
332  345  345 
333     // -------------------------------------------------------- Package Methods 346     // -------------------------------------------------------- Package Methods 346     // -------------------------------------------------------- Package Methods
334  347  347 
335  348  348 
336     /** 349     /** 349     /**
337      * Process an incoming TCP/IP connection on the specified socket.  Any 350      * Process an incoming TCP/IP connection on the specified socket.  Any 350      * Process an incoming TCP/IP connection on the specified socket.  Any
338      * exception that occurs during processing must be logged and swallowed. 351      * exception that occurs during processing must be logged and swallowed. 351      * exception that occurs during processing must be logged and swallowed.
339      * <b>NOTE</b>:  This method is called from our Connector's thread.  We 352      * <b>NOTE</b>:  This method is called from our Connector's thread.  We 352      * <b>NOTE</b>:  This method is called from our Connector's thread.  We
340      * must assign it to our own thread so that multiple simultaneous 353      * must assign it to our own thread so that multiple simultaneous 353      * must assign it to our own thread so that multiple simultaneous
341      * requests can be handled. 354      * requests can be handled. 354      * requests can be handled.
342      * 355      * 355      *
343      * @param socket TCP socket to process 356      * @param socket TCP socket to process 356      * @param socket TCP socket to process
344      */ 357      */ 357      */
345     synchronized void assign(Socket socket) { 358     synchronized void assign(Socket socket) { 358     synchronized void assign(Socket socket) {
346  359  359 
347         // Wait for the Processor to get the previous Socket 360         // Wait for the Processor to get the previous Socket 360         // Wait for the Processor to get the previous Socket
348         while (available) { 361         while (available) { 361         while (available) {
349             try { 362             try { 362             try {
350                 wait(); 363                 wait(); 363                 wait();
351             } catch (InterruptedException e) { 364             } catch (InterruptedException e) { 364             } catch (InterruptedException e) {
352             } 365             } 365             }
353         } 366         } 366         }
354  367  367 
355         // Store the newly available Socket and notify our thread 368         // Store the newly available Socket and notify our thread 368         // Store the newly available Socket and notify our thread
356         this.socket = socket; 369         this.socket = socket; 369         this.socket = socket;
357         available = true; 370         available = true; 370         available = true;
358         notifyAll(); 371         notifyAll(); 371         notifyAll();
359  372  372 
360         if ((debug >= 1) && (socket != null)) 373         if ((debug >= 1) && (socket != null)) 373         if ((debug >= 1) && (socket != null))
361             log(" An incoming request is being assigned"); 374             log(" An incoming request is being assigned"); 374             log(" An incoming request is being assigned");
362  375  375 
363     } 376     } 376     }
364  377  377 
365  378  378 
366     // -------------------------------------------------------- Private Methods 379     // -------------------------------------------------------- Private Methods 379     // -------------------------------------------------------- Private Methods
367  380  380 
368  381  381 
369     /** 382     /** 382     /**
370      * Await a newly assigned Socket from our Connector, or <code>null</code> 383      * Await a newly assigned Socket from our Connector, or <code>null</code> 383      * Await a newly assigned Socket from our Connector, or <code>null</code>
371      * if we are supposed to shut down. 384      * if we are supposed to shut down. 384      * if we are supposed to shut down.
372      */ 385      */ 385      */
373     private synchronized Socket await() { 386     private synchronized Socket await() { 386     private synchronized Socket await() {
374  387  387 
375         // Wait for the Connector to provide a new Socket 388         // Wait for the Connector to provide a new Socket 388         // Wait for the Connector to provide a new Socket
376         while (!available) { 389         while (!available) { 389         while (!available) {
377             try { 390             try { 390             try {
378                 wait(); 391                 wait(); 391                 wait();
379             } catch (InterruptedException e) { 392             } catch (InterruptedException e) { 392             } catch (InterruptedException e) {
380             } 393             } 393             }
381         } 394         } 394         }
382  395  395 
383         // Notify the Connector that we have received this Socket 396         // Notify the Connector that we have received this Socket 396         // Notify the Connector that we have received this Socket
384         Socket socket = this.socket; 397         Socket socket = this.socket; 397         Socket socket = this.socket;
385         available = false; 398         available = false; 398         available = false;
386         notifyAll(); 399         notifyAll(); 399         notifyAll();
387  400  400 
388         if ((debug >= 1) && (socket != null)) 401         if ((debug >= 1) && (socket != null)) 401         if ((debug >= 1) && (socket != null))
389             log("  The incoming request has been awaited"); 402             log("  The incoming request has been awaited"); 402             log("  The incoming request has been awaited");
390  403  403 
391         return (socket); 404         return (socket); 404         return (socket);
392  405  405 
393     } 406     } 406     }
394  407  407 
395  408  408 
396  409  409 
397     /** 410     /** 410     /**
398      * Log a message on the Logger associated with our Container (if any) 411      * Log a message on the Logger associated with our Container (if any) 411      * Log a message on the Logger associated with our Container (if any)
399      * 412      * 412      *
400      * @param message Message to be logged 413      * @param message Message to be logged 413      * @param message Message to be logged
401      */ 414      */ 414      */
402     private void log(String message) { 415     private void log(String message) { 415     private void log(String message) {
403  416  416 
404         Logger logger = connector.getContainer().getLogger(); 417         Logger logger = connector.getContainer().getLogger(); 417         Logger logger = connector.getContainer().getLogger();
405         if (logger != null) 418         if (logger != null) 418         if (logger != null)
406             logger.log(threadName + " " + message); 419             logger.log(threadName + " " + message); 419             logger.log(threadName + " " + message);
407  420  420 
408     } 421     } 421     }
409  422  422 
410  423  423 
411     /** 424     /** 424     /**
412      * Log a message on the Logger associated with our Container (if any) 425      * Log a message on the Logger associated with our Container (if any) 425      * Log a message on the Logger associated with our Container (if any)
413      * 426      * 426      *
414      * @param message Message to be logged 427      * @param message Message to be logged 427      * @param message Message to be logged
415      * @param throwable Associated exception 428      * @param throwable Associated exception 428      * @param throwable Associated exception
416      */ 429      */ 429      */
417     private void log(String message, Throwable throwable) { 430     private void log(String message, Throwable throwable) { 430     private void log(String message, Throwable throwable) {
418  431  431 
419         Logger logger = connector.getContainer().getLogger(); 432         Logger logger = connector.getContainer().getLogger(); 432         Logger logger = connector.getContainer().getLogger();
420         if (logger != null) 433         if (logger != null) 433         if (logger != null)
421             logger.log(threadName + " " + message, throwable); 434             logger.log(threadName + " " + message, throwable); 434             logger.log(threadName + " " + message, throwable);
422  435  435 
423     } 436     } 436     }
424  437  437 
425  438  438 
426     /** 439     /** 439     /**
427      * Parse the value of an <code>Accept-Language</code> header, and add 440      * Parse the value of an <code>Accept-Language</code> header, and add 440      * Parse the value of an <code>Accept-Language</code> header, and add
428      * the corresponding Locales to the current request. 441      * the corresponding Locales to the current request. 441      * the corresponding Locales to the current request.
429      * 442      * 442      *
430      * @param value The value of the <code>Accept-Language</code> header. 443      * @param value The value of the <code>Accept-Language</code> header. 443      * @param value The value of the <code>Accept-Language</code> header.
431      */ 444      */ 444      */
432     private void parseAcceptLanguage(String value) { 445     private void parseAcceptLanguage(String value) { 445     private void parseAcceptLanguage(String value) {
433  446  446 
434         // Store the accumulated languages that have been requested in 447         // Store the accumulated languages that have been requested in 447         // Store the accumulated languages that have been requested in
435         // a local collection, sorted by the quality value (so we can 448         // a local collection, sorted by the quality value (so we can 448         // a local collection, sorted by the quality value (so we can
436         // add Locales in descending order).  The values will be ArrayLists 449         // add Locales in descending order).  The values will be ArrayLists 449         // add Locales in descending order).  The values will be ArrayLists
437         // containing the corresponding Locales to be added 450         // containing the corresponding Locales to be added 450         // containing the corresponding Locales to be added
438         TreeMap locales = new TreeMap(); 451         TreeMap locales = new TreeMap(); 451         TreeMap locales = new TreeMap();
439  452  452 
440         // Preprocess the value to remove all whitespace 453         // Preprocess the value to remove all whitespace 453         // Preprocess the value to remove all whitespace
441         int white = value.indexOf(' '); 454         int white = value.indexOf(' '); 454         int white = value.indexOf(' ');
442         if (white < 0) 455         if (white < 0) 455         if (white < 0)
443             white = value.indexOf('\t'); 456             white = value.indexOf('\t'); 456             white = value.indexOf('\t');
444         if (white >= 0) { 457         if (white >= 0) { 457         if (white >= 0) {
445             StringBuffer sb = new StringBuffer(); 458             StringBuffer sb = new StringBuffer(); 458             StringBuffer sb = new StringBuffer();
446             int len = value.length(); 459             int len = value.length(); 459             int len = value.length();
447             for (int i = 0; i < len; i++) { 460             for (int i = 0; i < len; i++) { 460             for (int i = 0; i < len; i++) {
448                 char ch = value.charAt(i); 461                 char ch = value.charAt(i); 461                 char ch = value.charAt(i);
449                 if ((ch != ' ') && (ch != '\t')) 462                 if ((ch != ' ') && (ch != '\t')) 462                 if ((ch != ' ') && (ch != '\t'))
450                     sb.append(ch); 463                     sb.append(ch); 463                     sb.append(ch);
451             } 464             } 464             }
452             value = sb.toString(); 465             value = sb.toString(); 465             value = sb.toString();
453         } 466         } 466         }
454  467  467 
455         // Process each comma-delimited language specification 468         // Process each comma-delimited language specification 468         // Process each comma-delimited language specification
456         parser.setString(value);        // ASSERT: parser is available to us 469         parser.setString(value);        // ASSERT: parser is available to us 469         parser.setString(value);        // ASSERT: parser is available to us
457         int length = parser.getLength(); 470         int length = parser.getLength(); 470         int length = parser.getLength();
458         while (true) { 471         while (true) { 471         while (true) {
459  472  472 
460             // Extract the next comma-delimited entry 473             // Extract the next comma-delimited entry 473             // Extract the next comma-delimited entry
461             int start = parser.getIndex(); 474             int start = parser.getIndex(); 474             int start = parser.getIndex();
462             if (start >= length) 475             if (start >= length) 475             if (start >= length)
463                 break; 476                 break; 476                 break;
464             int end = parser.findChar(','); 477             int end = parser.findChar(','); 477             int end = parser.findChar(',');
465             String entry = parser.extract(start, end).trim(); 478             String entry = parser.extract(start, end).trim(); 478             String entry = parser.extract(start, end).trim();
466             parser.advance();   // For the following entry 479             parser.advance();   // For the following entry 479             parser.advance();   // For the following entry
467  480  480 
468             // Extract the quality factor for this entry 481             // Extract the quality factor for this entry 481             // Extract the quality factor for this entry
469             double quality = 1.0; 482             double quality = 1.0; 482             double quality = 1.0;
470             int semi = entry.indexOf(";q="); 483             int semi = entry.indexOf(";q="); 483             int semi = entry.indexOf(";q=");
471             if (semi >= 0) { 484             if (semi >= 0) { 484             if (semi >= 0) {
472                 try { 485                 try { 485                 try {
473                     quality = Double.parseDouble(entry.substring(semi + 3)); 486                     quality = Double.parseDouble(entry.substring(semi + 3)); 486                     quality = Double.parseDouble(entry.substring(semi + 3));
474                 } catch (NumberFormatException e) { 487                 } catch (NumberFormatException e) { 487                 } catch (NumberFormatException e) {
475                     quality = 0.0; 488                     quality = 0.0; 488                     quality = 0.0;
476                 } 489                 } 489                 }
477                 entry = entry.substring(0, semi); 490                 entry = entry.substring(0, semi); 490                 entry = entry.substring(0, semi);
478             } 491             } 491             }
479  492  492 
480             // Skip entries we are not going to keep track of 493             // Skip entries we are not going to keep track of 493             // Skip entries we are not going to keep track of
481             if (quality < 0.00005) 494             if (quality < 0.00005) 494             if (quality < 0.00005)
482                 continue;       // Zero (or effectively zero) quality factors 495                 continue;       // Zero (or effectively zero) quality factors 495                 continue;       // Zero (or effectively zero) quality factors
483             if ("*".equals(entry)) 496             if ("*".equals(entry)) 496             if ("*".equals(entry))
484                 continue;       // FIXME - "*" entries are not handled 497                 continue;       // FIXME - "*" entries are not handled 497                 continue;       // FIXME - "*" entries are not handled
485  498  498 
486             // Extract the language and country for this entry 499             // Extract the language and country for this entry 499             // Extract the language and country for this entry
487             String language = null; 500             String language = null; 500             String language = null;
488             String country = null; 501             String country = null; 501             String country = null;
489             String variant = null; 502             String variant = null; 502             String variant = null;
490             int dash = entry.indexOf('-'); 503             int dash = entry.indexOf('-'); 503             int dash = entry.indexOf('-');
491             if (dash < 0) { 504             if (dash < 0) { 504             if (dash < 0) {
492                 language = entry; 505                 language = entry; 505                 language = entry;
493                 country = ""; 506                 country = ""; 506                 country = "";
494                 variant = ""; 507                 variant = ""; 507                 variant = "";
495             } else { 508             } else { 508             } else {
496                 language = entry.substring(0, dash); 509                 language = entry.substring(0, dash); 509                 language = entry.substring(0, dash);
497                 country = entry.substring(dash + 1); 510                 country = entry.substring(dash + 1); 510                 country = entry.substring(dash + 1);
498                 int vDash = country.indexOf('-'); 511                 int vDash = country.indexOf('-'); 511                 int vDash = country.indexOf('-');
499                 if (vDash > 0) { 512                 if (vDash > 0) { 512                 if (vDash > 0) {
500                     String cTemp = country.substring(0, vDash); 513                     String cTemp = country.substring(0, vDash); 513                     String cTemp = country.substring(0, vDash);
501                     variant = country.substring(vDash + 1); 514                     variant = country.substring(vDash + 1); 514                     variant = country.substring(vDash + 1);
502                     country = cTemp; 515                     country = cTemp; 515                     country = cTemp;
503                 } else { 516                 } else { 516                 } else {
504                     variant = ""; 517                     variant = ""; 517                     variant = "";
505                 } 518                 } 518                 }
506             } 519             } 519             }
507  520  520 
508             // Add a new Locale to the list of Locales for this quality level 521             // Add a new Locale to the list of Locales for this quality level 521             // Add a new Locale to the list of Locales for this quality level
509             Locale locale = new Locale(language, country, variant); 522             Locale locale = new Locale(language, country, variant); 522             Locale locale = new Locale(language, country, variant);
510             Double key = new Double(-quality);  // Reverse the order 523             Double key = new Double(-quality);  // Reverse the order 523             Double key = new Double(-quality);  // Reverse the order
511             ArrayList values = (ArrayList) locales.get(key); 524             ArrayList values = (ArrayList) locales.get(key); 524             ArrayList values = (ArrayList) locales.get(key);
512             if (values == null) { 525             if (values == null) { 525             if (values == null) {
513                 values = new ArrayList(); 526                 values = new ArrayList(); 526                 values = new ArrayList();
514                 locales.put(key, values); 527                 locales.put(key, values); 527                 locales.put(key, values);
515             } 528             } 528             }
516             values.add(locale); 529             values.add(locale); 529             values.add(locale);
517  530  530 
518         } 531         } 531         }
519  532  532 
520         // Process the quality values in highest->lowest order (due to 533         // Process the quality values in highest->lowest order (due to 533         // Process the quality values in highest->lowest order (due to
521         // negating the Double value when creating the key) 534         // negating the Double value when creating the key) 534         // negating the Double value when creating the key)
522         Iterator keys = locales.keySet().iterator(); 535         Iterator keys = locales.keySet().iterator(); 535         Iterator keys = locales.keySet().iterator();
523         while (keys.hasNext()) { 536         while (keys.hasNext()) { 536         while (keys.hasNext()) {
524             Double key = (Double) keys.next(); 537             Double key = (Double) keys.next(); 537             Double key = (Double) keys.next();
525             ArrayList list = (ArrayList) locales.get(key); 538             ArrayList list = (ArrayList) locales.get(key); 538             ArrayList list = (ArrayList) locales.get(key);
526             Iterator values = list.iterator(); 539             Iterator values = list.iterator(); 539             Iterator values = list.iterator();
527             while (values.hasNext()) { 540             while (values.hasNext()) { 540             while (values.hasNext()) {
528                 Locale locale = (Locale) values.next(); 541                 Locale locale = (Locale) values.next(); 541                 Locale locale = (Locale) values.next();
529                 if (debug >= 1) 542                 if (debug >= 1) 542                 if (debug >= 1)
530                     log(" Adding locale '" + locale + "'"); 543                     log(" Adding locale '" + locale + "'"); 543                     log(" Adding locale '" + locale + "'");
531                 request.addLocale(locale); 544                 request.addLocale(locale); 544                 request.addLocale(locale);
532             } 545             } 545             }
533         } 546         } 546         }
534  547  547 
535     } 548     } 548     }
536  549  549 
537  550  550 
538     /** 551     /** 551     /**
539      * Parse and record the connection parameters related to this request. 552      * Parse and record the connection parameters related to this request. 552      * Parse and record the connection parameters related to this request.
540      * 553      * 553      *
541      * @param socket The socket on which we are connected 554      * @param socket The socket on which we are connected 554      * @param socket The socket on which we are connected
542      * 555      * 555      *
543      * @exception IOException if an input/output error occurs 556      * @exception IOException if an input/output error occurs 556      * @exception IOException if an input/output error occurs
544      * @exception ServletException if a parsing error occurs 557      * @exception ServletException if a parsing error occurs 557      * @exception ServletException if a parsing error occurs
545      */ 558      */ 558      */
546     private void parseConnection(Socket socket) 559     private void parseConnection(Socket socket) 559     private void parseConnection(Socket socket)
547         throws IOException, ServletException { 560         throws IOException, ServletException { 560         throws IOException, ServletException {
548  561  561 
549         if (debug >= 2) 562         if (debug >= 2) 562         if (debug >= 2)
550             log("  parseConnection: address=" + socket.getInetAddress() + 563             log("  parseConnection: address=" + socket.getInetAddress() + 563             log("  parseConnection: address=" + socket.getInetAddress() +
551                 ", port=" + connector.getPort()); 564                 ", port=" + connector.getPort()); 564                 ", port=" + connector.getPort());
552         ((HttpRequestImpl) request).setInet(socket.getInetAddress()); 565         ((HttpRequestImpl) request).setInet(socket.getInetAddress()); 565         ((HttpRequestImpl) request).setInet(socket.getInetAddress());
553         if (proxyPort != 0) 566         if (proxyPort != 0) 566         if (proxyPort != 0)
554             request.setServerPort(proxyPort); 567             request.setServerPort(proxyPort); 567             request.setServerPort(proxyPort);
555         else 568         else 568         else
556             request.setServerPort(serverPort); 569             request.setServerPort(serverPort); 569             request.setServerPort(serverPort);
557         request.setSocket(socket); 570         request.setSocket(socket); 570         request.setSocket(socket);
558  571  571 
559     } 572     } 572     }
560  573  573 
561  574  574 
562     /** 575     /** 575     /**
563      * Parse the incoming HTTP request headers, and set the appropriate 576      * Parse the incoming HTTP request headers, and set the appropriate 576      * Parse the incoming HTTP request headers, and set the appropriate
564      * request headers. 577      * request headers. 577      * request headers.
565      * 578      * 578      *
566      * @param input The input stream connected to our socket 579      * @param input The input stream connected to our socket 579      * @param input The input stream connected to our socket
567      * 580      * 580      *
568      * @exception IOException if an input/output error occurs 581      * @exception IOException if an input/output error occurs 581      * @exception IOException if an input/output error occurs
569      * @exception ServletException if a parsing error occurs 582      * @exception ServletException if a parsing error occurs 582      * @exception ServletException if a parsing error occurs
570      */ 583      */ 583      */
571     private void parseHeaders(SocketInputStream input) 584     private void parseHeaders(SocketInputStream input) 584     private void parseHeaders(SocketInputStream input)
572         throws IOException, ServletException { 585         throws IOException, ServletException { 585         throws IOException, ServletException {
573  586  586 
574         while (true) { 587         while (true) { 587         while (true) {
575  588  588 
576             HttpHeader header = request.allocateHeader(); 589             HttpHeader header = request.allocateHeader(); 589             HttpHeader header = request.allocateHeader();
577  590  590 
578             // Read the next header 591             // Read the next header 591             // Read the next header
579             input.readHeader(header); 592             input.readHeader(header); 592             input.readHeader(header);
580             if (header.nameEnd == 0) { 593             if (header.nameEnd == 0) { 593             if (header.nameEnd == 0) {
581                 if (header.valueEnd == 0) { 594                 if (header.valueEnd == 0) { 594                 if (header.valueEnd == 0) {
582                     return; 595                     return; 595                     return;
583                 } else { 596                 } else { 596                 } else {
584                     throw new ServletException 597                     throw new ServletException 597                     throw new ServletException
585                         (sm.getString("httpProcessor.parseHeaders.colon")); 598                         (sm.getString("httpProcessor.parseHeaders.colon")); 598                         (sm.getString("httpProcessor.parseHeaders.colon"));
586                 } 599                 } 599                 }
587             } 600             } 600             }
588  601  601 
589             String value = new String(header.value, 0, header.valueEnd); 602             String value = new String(header.value, 0, header.valueEnd); 602             String value = new String(header.value, 0, header.valueEnd);
590             if (debug >= 1) 603             if (debug >= 1) 603             if (debug >= 1)
591                 log(" Header " + new String(header.name, 0, header.nameEnd) 604                 log(" Header " + new String(header.name, 0, header.nameEnd) 604                 log(" Header " + new String(header.name, 0, header.nameEnd)
592                     + " = " + value); 605                     + " = " + value); 605                     + " = " + value);
593  606  606 
594             // Set the corresponding request headers 607             // Set the corresponding request headers 607             // Set the corresponding request headers
595             if (header.equals(DefaultHeaders.AUTHORIZATION_NAME)) { 608             if (header.equals(DefaultHeaders.AUTHORIZATION_NAME)) { 608             if (header.equals(DefaultHeaders.AUTHORIZATION_NAME)) {
596                 request.setAuthorization(value); 609                 request.setAuthorization(value); 609                 request.setAuthorization(value);
597             } else if (header.equals(DefaultHeaders.ACCEPT_LANGUAGE_NAME)) { 610             } else if (header.equals(DefaultHeaders.ACCEPT_LANGUAGE_NAME)) { 610             } else if (header.equals(DefaultHeaders.ACCEPT_LANGUAGE_NAME)) {
598                 parseAcceptLanguage(value); 611                 parseAcceptLanguage(value); 611                 parseAcceptLanguage(value);
599             } else if (header.equals(DefaultHeaders.COOKIE_NAME)) { 612             } else if (header.equals(DefaultHeaders.COOKIE_NAME)) { 612             } else if (header.equals(DefaultHeaders.COOKIE_NAME)) {
600                 Cookie cookies[] = RequestUtil.parseCookieHeader(value); 613                 Cookie cookies[] = RequestUtil.parseCookieHeader(value); 613                 Cookie cookies[] = RequestUtil.parseCookieHeader(value);
601                 for (int i = 0; i < cookies.length; i++) { 614                 for (int i = 0; i < cookies.length; i++) { 614                 for (int i = 0; i < cookies.length; i++) {
602                     if (cookies[i].getName().equals 615                     if (cookies[i].getName().equals 615                     if (cookies[i].getName().equals
603                         (Globals.SESSION_COOKIE_NAME)) { 616                         (Globals.SESSION_COOKIE_NAME)) { 616                         (Globals.SESSION_COOKIE_NAME)) {
604                         // Override anything requested in the URL 617                         // Override anything requested in the URL 617                         // Override anything requested in the URL
605                         if (!request.isRequestedSessionIdFromCookie()) { 618                         if (!request.isRequestedSessionIdFromCookie()) { 618                         if (!request.isRequestedSessionIdFromCookie()) {
606                             // Accept only the first session id cookie 619                             // Accept only the first session id cookie 619                             // Accept only the first session id cookie
607                             request.setRequestedSessionId 620                             request.setRequestedSessionId 620                             request.setRequestedSessionId
608                                 (cookies[i].getValue()); 621                                 (cookies[i].getValue()); 621                                 (cookies[i].getValue());
609                             request.setRequestedSessionCookie(true); 622                             request.setRequestedSessionCookie(true); 622                             request.setRequestedSessionCookie(true);
610                             request.setRequestedSessionURL(false); 623                             request.setRequestedSessionURL(false); 623                             request.setRequestedSessionURL(false);
611                             if (debug >= 1) 624                             if (debug >= 1) 624                             if (debug >= 1)
612                                 log(" Requested cookie session id is " + 625                                 log(" Requested cookie session id is " + 625                                 log(" Requested cookie session id is " +
613                                     ((HttpServletRequest) request.getRequest()) 626                                     ((HttpServletRequest) request.getRequest()) 626                                     ((HttpServletRequest) request.getRequest())
614                                     .getRequestedSessionId()); 627                                     .getRequestedSessionId()); 627                                     .getRequestedSessionId());
615                         } 628                         } 628                         }
616                     } 629                     } 629                     }
617                     if (debug >= 1) 630                     if (debug >= 1) 630                     if (debug >= 1)
618                         log(" Adding cookie " + cookies[i].getName() + "=" + 631                         log(" Adding cookie " + cookies[i].getName() + "=" + 631                         log(" Adding cookie " + cookies[i].getName() + "=" +
619                             cookies[i].getValue()); 632                             cookies[i].getValue()); 632                             cookies[i].getValue());
620                     request.addCookie(cookies[i]); 633                     request.addCookie(cookies[i]); 633                     request.addCookie(cookies[i]);
621                 } 634                 } 634                 }
622             } else if (header.equals(DefaultHeaders.CONTENT_LENGTH_NAME)) { 635             } else if (header.equals(DefaultHeaders.CONTENT_LENGTH_NAME)) { 635             } else if (header.equals(DefaultHeaders.CONTENT_LENGTH_NAME)) {
623                 int n = -1; 636                 int n = -1; 636                 int n = -1;
624                 try { 637                 try { 637                 try {
625                     n = Integer.parseInt(value); 638                     n = Integer.parseInt(value); 638                     n = Integer.parseInt(value);
626                 } catch (Exception e) { 639                 } catch (Exception e) { 639                 } catch (Exception e) {
627                     throw new ServletException 640                     throw new ServletException 640                     throw new ServletException
628                         (sm.getString 641                         (sm.getString 641                         (sm.getString
629                          ("httpProcessor.parseHeaders.contentLength")); 642                          ("httpProcessor.parseHeaders.contentLength")); 642                          ("httpProcessor.parseHeaders.contentLength"));
630                 } 643                 } 643                 }
631                 request.setContentLength(n); 644                 request.setContentLength(n); 644                 request.setContentLength(n);
632             } else if (header.equals(DefaultHeaders.CONTENT_TYPE_NAME)) { 645             } else if (header.equals(DefaultHeaders.CONTENT_TYPE_NAME)) { 645             } else if (header.equals(DefaultHeaders.CONTENT_TYPE_NAME)) {
633                 request.setContentType(value); 646                 request.setContentType(value); 646                 request.setContentType(value);
634             } else if (header.equals(DefaultHeaders.HOST_NAME)) { 647             } else if (header.equals(DefaultHeaders.HOST_NAME)) { 647             } else if (header.equals(DefaultHeaders.HOST_NAME)) {
635                 int n = value.indexOf(':'); 648                 int n = value.indexOf(':'); 648                 int n = value.indexOf(':');
636                 if (n < 0) { 649                 if (n < 0) { 649                 if (n < 0) {
637                     if (connector.getScheme().equals("http")) { 650                     if (connector.getScheme().equals("http")) { 650                     if (connector.getScheme().equals("http")) {
638                         request.setServerPort(80); 651                         request.setServerPort(80); 651                         request.setServerPort(80);
639                     } else if (connector.getScheme().equals("https")) { 652                     } else if (connector.getScheme().equals("https")) { 652                     } else if (connector.getScheme().equals("https")) {
640                         request.setServerPort(443); 653                         request.setServerPort(443); 653                         request.setServerPort(443);
641                     } 654                     } 654                     }
642                     if (proxyName != null) 655                     if (proxyName != null) 655                     if (proxyName != null)
643                         request.setServerName(proxyName); 656                         request.setServerName(proxyName); 656                         request.setServerName(proxyName);
644                     else 657                     else 657                     else
645                         request.setServerName(value); 658                         request.setServerName(value); 658                         request.setServerName(value);
646                 } else { 659                 } else { 659                 } else {
647                     if (proxyName != null) 660                     if (proxyName != null) 660                     if (proxyName != null)
648                         request.setServerName(proxyName); 661                         request.setServerName(proxyName); 661                         request.setServerName(proxyName);
649                     else 662                     else 662                     else
650                         request.setServerName(value.substring(0, n).trim()); 663                         request.setServerName(value.substring(0, n).trim()); 663                         request.setServerName(value.substring(0, n).trim());
651                     if (proxyPort != 0) 664                     if (proxyPort != 0) 664                     if (proxyPort != 0)
652                         request.setServerPort(proxyPort); 665                         request.setServerPort(proxyPort); 665                         request.setServerPort(proxyPort);
653                     else { 666                     else { 666                     else {
654                         int port = 80; 667                         int port = 80; 667                         int port = 80;
655                         try { 668                         try { 668                         try {
656                             port = 669                             port = 669                             port =
657                                 Integer.parseInt(value.substring(n+1).trim()); 670                                 Integer.parseInt(value.substring(n+1).trim()); 670                                 Integer.parseInt(value.substring(n+1).trim());
658                         } catch (Exception e) { 671                         } catch (Exception e) { 671                         } catch (Exception e) {
659                             throw new ServletException 672                             throw new ServletException 672                             throw new ServletException
660                                 (sm.getString 673                                 (sm.getString 673                                 (sm.getString
661                                  ("httpProcessor.parseHeaders.portNumber")); 674                                  ("httpProcessor.parseHeaders.portNumber")); 674                                  ("httpProcessor.parseHeaders.portNumber"));
662                         } 675                         } 675                         }
663                         request.setServerPort(port); 676                         request.setServerPort(port); 676                         request.setServerPort(port);
664                     } 677                     } 677                     }
665                 } 678                 } 678                 }
666             } else if (header.equals(DefaultHeaders.CONNECTION_NAME)) { 679             } else if (header.equals(DefaultHeaders.CONNECTION_NAME)) { 679             } else if (header.equals(DefaultHeaders.CONNECTION_NAME)) {
667                 if (header.valueEquals 680                 if (header.valueEquals 680                 if (header.valueEquals
668                     (DefaultHeaders.CONNECTION_CLOSE_VALUE)) { 681                     (DefaultHeaders.CONNECTION_CLOSE_VALUE)) { 681                     (DefaultHeaders.CONNECTION_CLOSE_VALUE)) {
669                     keepAlive = false; 682                     keepAlive = false; 682                     keepAlive = false;
670                     response.setHeader("Connection", "close"); 683                     response.setHeader("Connection", "close"); 683                     response.setHeader("Connection", "close");
671                 } 684                 } 684                 }
672                 //request.setConnection(header); 685                 //request.setConnection(header); 685                 //request.setConnection(header);
673                 /* 686                 /* 686                 /*
674                   if ("keep-alive".equalsIgnoreCase(value)) { 687                   if ("keep-alive".equalsIgnoreCase(value)) { 687                   if ("keep-alive".equalsIgnoreCase(value)) {
675                   keepAlive = true; 688                   keepAlive = true; 688                   keepAlive = true;
676                   } 689                   } 689                   }
677                 */ 690                 */ 690                 */
678             } else if (header.equals(DefaultHeaders.EXPECT_NAME)) { 691             } else if (header.equals(DefaultHeaders.EXPECT_NAME)) { 691             } else if (header.equals(DefaultHeaders.EXPECT_NAME)) {
679                 if (header.valueEquals(DefaultHeaders.EXPECT_100_VALUE)) 692                 if (header.valueEquals(DefaultHeaders.EXPECT_100_VALUE)) 692                 if (header.valueEquals(DefaultHeaders.EXPECT_100_VALUE))
680                     sendAck = true; 693                     sendAck = true; 693                     sendAck = true;
681                 else 694                 else 694                 else
682                     throw new ServletException 695                     throw new ServletException 695                     throw new ServletException
683                         (sm.getString 696                         (sm.getString 696                         (sm.getString
684                          ("httpProcessor.parseHeaders.unknownExpectation")); 697                          ("httpProcessor.parseHeaders.unknownExpectation")); 697                          ("httpProcessor.parseHeaders.unknownExpectation"));
685             } else if (header.equals(DefaultHeaders.TRANSFER_ENCODING_NAME)) { 698             } else if (header.equals(DefaultHeaders.TRANSFER_ENCODING_NAME)) { 698             } else if (header.equals(DefaultHeaders.TRANSFER_ENCODING_NAME)) {
686                 //request.setTransferEncoding(header); 699                 //request.setTransferEncoding(header); 699                 //request.setTransferEncoding(header);
687             } 700             } 700             }
688  701  701 
689             request.nextHeader(); 702             request.nextHeader(); 702             request.nextHeader();
690  703  703 
691         } 704         } 704         }
692  705  705 
693     } 706     } 706     }
694  707  707 
695  708  708 
696     /** 709     /** 709     /**
697      * Parse the incoming HTTP request and set the corresponding HTTP request 710      * Parse the incoming HTTP request and set the corresponding HTTP request 710      * Parse the incoming HTTP request and set the corresponding HTTP request
698      * properties. 711      * properties. 711      * properties.
699      * 712      * 712      *
700      * @param input The input stream attached to our socket 713      * @param input The input stream attached to our socket 713      * @param input The input stream attached to our socket
701      * @param output The output stream of the socket 714      * @param output The output stream of the socket 714      * @param output The output stream of the socket
702      * 715      * 715      *
703      * @exception IOException if an input/output error occurs 716      * @exception IOException if an input/output error occurs 716      * @exception IOException if an input/output error occurs
704      * @exception ServletException if a parsing error occurs 717      * @exception ServletException if a parsing error occurs 717      * @exception ServletException if a parsing error occurs
705      */ 718      */ 718      */
706     private void parseRequest(SocketInputStream input, OutputStream output) 719     private void parseRequest(SocketInputStream input, OutputStream output) 719     private void parseRequest(SocketInputStream input, OutputStream output)
707         throws IOException, ServletException { 720         throws IOException, ServletException { 720         throws IOException, ServletException {
708  721  721 
709         // Parse the incoming request line 722         // Parse the incoming request line 722         // Parse the incoming request line
710         input.readRequestLine(requestLine); 723         input.readRequestLine(requestLine); 723         input.readRequestLine(requestLine);
711          724          724         
712         // When the previous method returns, we're actually processing a  725         // When the previous method returns, we're actually processing a  725         // When the previous method returns, we're actually processing a 
713         // request 726         // request 726         // request
714         status = Constants.PROCESSOR_ACTIVE; 727         status = Constants.PROCESSOR_ACTIVE; 727         status = Constants.PROCESSOR_ACTIVE;
715          728          728         
716         String method = 729         String method = 729         String method =
717             new String(requestLine.method, 0, requestLine.methodEnd); 730             new String(requestLine.method, 0, requestLine.methodEnd); 730             new String(requestLine.method, 0, requestLine.methodEnd);
718         String uri = null; 731         String uri = null; 731         String uri = null;
719         String protocol = new String(requestLine.protocol, 0, 732         String protocol = new String(requestLine.protocol, 0, 732         String protocol = new String(requestLine.protocol, 0,
720                                      requestLine.protocolEnd); 733                                      requestLine.protocolEnd); 733                                      requestLine.protocolEnd);
721  734  734 
722         //System.out.println(" Method:" + method + "_ Uri:" + uri 735         //System.out.println(" Method:" + method + "_ Uri:" + uri 735         //System.out.println(" Method:" + method + "_ Uri:" + uri
723         //                   + "_ Protocol:" + protocol); 736         //                   + "_ Protocol:" + protocol); 736         //                   + "_ Protocol:" + protocol);
724  737  737 
725         if (protocol.length() == 0) 738         if (protocol.length() == 0) 738         if (protocol.length() == 0)
726             protocol = "HTTP/0.9"; 739             protocol = "HTTP/0.9"; 739             protocol = "HTTP/0.9";
727  740  740 
728         // Now check if the connection should be kept alive after parsing the 741         // Now check if the connection should be kept alive after parsing the 741         // Now check if the connection should be kept alive after parsing the
729         // request. 742         // request. 742         // request.
730         if ( protocol.equals("HTTP/1.1") ) { 743         if ( protocol.equals("HTTP/1.1") ) { 743         if ( protocol.equals("HTTP/1.1") ) {
731             http11 = true; 744             http11 = true; 744             http11 = true;
732             sendAck = false; 745             sendAck = false; 745             sendAck = false;
733         } else { 746         } else { 746         } else {
734             http11 = false; 747             http11 = false; 747             http11 = false;
735             sendAck = false; 748             sendAck = false; 748             sendAck = false;
736             // For HTTP/1.0, connection are not persistent by default, 749             // For HTTP/1.0, connection are not persistent by default, 749             // For HTTP/1.0, connection are not persistent by default,
737             // unless specified with a Connection: Keep-Alive header. 750             // unless specified with a Connection: Keep-Alive header. 750             // unless specified with a Connection: Keep-Alive header.
738             keepAlive = false; 751             keepAlive = false; 751             keepAlive = false;
739         } 752         } 752         }
740  753  753 
741         // Validate the incoming request line 754         // Validate the incoming request line 754         // Validate the incoming request line
742         if (method.length() < 1) { 755         if (method.length() < 1) { 755         if (method.length() < 1) {
743             throw new ServletException 756             throw new ServletException 756             throw new ServletException
744                 (sm.getString("httpProcessor.parseRequest.method")); 757                 (sm.getString("httpProcessor.parseRequest.method")); 757                 (sm.getString("httpProcessor.parseRequest.method"));
745         } else if (requestLine.uriEnd < 1) { 758         } else if (requestLine.uriEnd < 1) { 758         } else if (requestLine.uriEnd < 1) {
746             throw new ServletException 759             throw new ServletException 759             throw new ServletException
747                 (sm.getString("httpProcessor.parseRequest.uri")); 760                 (sm.getString("httpProcessor.parseRequest.uri")); 760                 (sm.getString("httpProcessor.parseRequest.uri"));
748         } 761         } 761         }
749  762  762 
750         // Parse any query parameters out of the request URI 763         // Parse any query parameters out of the request URI 763         // Parse any query parameters out of the request URI
751         int question = requestLine.indexOf("?"); 764         int question = requestLine.indexOf("?"); 764         int question = requestLine.indexOf("?");
752         if (question >= 0) { 765         if (question >= 0) { 765         if (question >= 0) {
753             request.setQueryString 766             request.setQueryString 766             request.setQueryString
754                 (new String(requestLine.uri, question + 1, 767                 (new String(requestLine.uri, question + 1, 767                 (new String(requestLine.uri, question + 1,
755                             requestLine.uriEnd - question - 1)); 768                             requestLine.uriEnd - question - 1)); 768                             requestLine.uriEnd - question - 1));
756             if (debug >= 1) 769             if (debug >= 1) 769             if (debug >= 1)
757                 log(" Query string is " + 770                 log(" Query string is " + 770                 log(" Query string is " +
758                     ((HttpServletRequest) request.getRequest()) 771                     ((HttpServletRequest) request.getRequest()) 771                     ((HttpServletRequest) request.getRequest())
759                     .getQueryString()); 772                     .getQueryString()); 772                     .getQueryString());
760             uri = new String(requestLine.uri, 0, question); 773             uri = new String(requestLine.uri, 0, question); 773             uri = new String(requestLine.uri, 0, question);
761         } else { 774         } else { 774         } else {
762             request.setQueryString(null); 775             request.setQueryString(null); 775             request.setQueryString(null);
763             uri = new String(requestLine.uri, 0, requestLine.uriEnd); 776             uri = new String(requestLine.uri, 0, requestLine.uriEnd); 776             uri = new String(requestLine.uri, 0, requestLine.uriEnd);
764         } 777         } 777         }
765  778  778 
766         // Checking for an absolute URI (with the HTTP protocol) 779         // Checking for an absolute URI (with the HTTP protocol) 779         // Checking for an absolute URI (with the HTTP protocol)
767         if (!uri.startsWith("/")) { 780         if (!uri.startsWith("/")) { 780         if (!uri.startsWith("/")) {
768             int pos = uri.indexOf("://"); 781             int pos = uri.indexOf("://"); 781             int pos = uri.indexOf("://");
769             // Parsing out protocol and host name 782             // Parsing out protocol and host name 782             // Parsing out protocol and host name
770             if (pos != -1) { 783             if (pos != -1) { 783             if (pos != -1) {
771                 pos = uri.indexOf('/', pos + 3); 784                 pos = uri.indexOf('/', pos + 3); 784                 pos = uri.indexOf('/', pos + 3);
772                 if (pos == -1) { 785                 if (pos == -1) { 785                 if (pos == -1) {
773                     uri = ""; 786                     uri = ""; 786                     uri = "";
774                 } else { 787                 } else { 787                 } else {
775                     uri = uri.substring(pos); 788                     uri = uri.substring(pos); 788                     uri = uri.substring(pos);
776                 } 789                 } 789                 }
777             } 790             } 790             }
778         } 791         } 791         }
779  792  792 
780         // Parse any requested session ID out of the request URI 793         // Parse any requested session ID out of the request URI 793         // Parse any requested session ID out of the request URI
781         int semicolon = uri.indexOf(match); 794         int semicolon = uri.indexOf(match); 794         int semicolon = uri.indexOf(match);
782         if (semicolon >= 0) { 795         if (semicolon >= 0) { 795         if (semicolon >= 0) {
783             String rest = uri.substring(semicolon + match.length()); 796             String rest = uri.substring(semicolon + match.length()); 796             String rest = uri.substring(semicolon + match.length());
784             int semicolon2 = rest.indexOf(';'); 797             int semicolon2 = rest.indexOf(';'); 797             int semicolon2 = rest.indexOf(';');
785             if (semicolon2 >= 0) { 798             if (semicolon2 >= 0) { 798             if (semicolon2 >= 0) {
786                 request.setRequestedSessionId(rest.substring(0, semicolon2)); 799                 request.setRequestedSessionId(rest.substring(0, semicolon2)); 799                 request.setRequestedSessionId(rest.substring(0, semicolon2));
787                 rest = rest.substring(semicolon2); 800                 rest = rest.substring(semicolon2); 800                 rest = rest.substring(semicolon2);
788             } else { 801             } else { 801             } else {
789                 request.setRequestedSessionId(rest); 802                 request.setRequestedSessionId(rest); 802                 request.setRequestedSessionId(rest);
790                 rest = ""; 803                 rest = ""; 803                 rest = "";
791             } 804             } 804             }
792             request.setRequestedSessionURL(true); 805             request.setRequestedSessionURL(true); 805             request.setRequestedSessionURL(true);
793             uri = uri.substring(0, semicolon) + rest; 806             uri = uri.substring(0, semicolon) + rest; 806             uri = uri.substring(0, semicolon) + rest;
794             if (debug >= 1) 807             if (debug >= 1) 807             if (debug >= 1)
795                 log(" Requested URL session id is " + 808                 log(" Requested URL session id is " + 808                 log(" Requested URL session id is " +
796                     ((HttpServletRequest) request.getRequest()) 809                     ((HttpServletRequest) request.getRequest()) 809                     ((HttpServletRequest) request.getRequest())
797                     .getRequestedSessionId()); 810                     .getRequestedSessionId()); 810                     .getRequestedSessionId());
798         } else { 811         } else { 811         } else {
799             request.setRequestedSessionId(null); 812             request.setRequestedSessionId(null); 812             request.setRequestedSessionId(null);
800             request.setRequestedSessionURL(false); 813             request.setRequestedSessionURL(false); 813             request.setRequestedSessionURL(false);
801         } 814         } 814         }
802  815  815 
803         // Normalize URI (using String operations at the moment) 816         // Normalize URI (using String operations at the moment) 816         // Normalize URI (using String operations at the moment)
804         String normalizedUri = normalize(uri); 817         String normalizedUri = normalize(uri); 817         String normalizedUri = normalize(uri);
805         if (debug >= 1) 818         if (debug >= 1) 818         if (debug >= 1)
806             log("Normalized: '" + uri + "' to '" + normalizedUri + "'"); 819             log("Normalized: '" + uri + "' to '" + normalizedUri + "'"); 819             log("Normalized: '" + uri + "' to '" + normalizedUri + "'");
807  820  820 
808         // Set the corresponding request properties 821         // Set the corresponding request properties 821         // Set the corresponding request properties
809         ((HttpRequest) request).setMethod(method); 822         ((HttpRequest) request).setMethod(method); 822         ((HttpRequest) request).setMethod(method);
810         request.setProtocol(protocol); 823         request.setProtocol(protocol); 823         request.setProtocol(protocol);
811         if (normalizedUri != null) { 824         if (normalizedUri != null) { 824         if (normalizedUri != null) {
812             ((HttpRequest) request).setRequestURI(normalizedUri); 825             ((HttpRequest) request).setRequestURI(normalizedUri); 825             ((HttpRequest) request).setRequestURI(normalizedUri);
813         } else { 826         } else { 826         } else {
814             ((HttpRequest) request).setRequestURI(uri); 827             ((HttpRequest) request).setRequestURI(uri); 827             ((HttpRequest) request).setRequestURI(uri);
815         } 828         } 828         }
816         request.setSecure(connector.getSecure()); 829         request.setSecure(connector.getSecure()); 829         request.setSecure(connector.getSecure());
817         request.setScheme(connector.getScheme()); 830         request.setScheme(connector.getScheme()); 830         request.setScheme(connector.getScheme());
818  831  831 
819         if (normalizedUri == null) { 832         if (normalizedUri == null) { 832         if (normalizedUri == null) {
820             log(" Invalid request URI: '" + uri + "'"); 833             log(" Invalid request URI: '" + uri + "'"); 833             log(" Invalid request URI: '" + uri + "'");
821             throw new ServletException("Invalid URI: " + uri + "'"); 834             throw new ServletException("Invalid URI: " + uri + "'"); 834             throw new ServletException("Invalid URI: " + uri + "'");
822         } 835         } 835         }
823  836  836 
824         if (debug >= 1) 837         if (debug >= 1) 837         if (debug >= 1)
825             log(" Request is '" + method + "' for '" + uri + 838             log(" Request is '" + method + "' for '" + uri + 838             log(" Request is '" + method + "' for '" + uri +
826                 "' with protocol '" + protocol + "'"); 839                 "' with protocol '" + protocol + "'"); 839                 "' with protocol '" + protocol + "'");
827  840  840 
828     } 841     } 841     }
829  842  842 
830  843  843 
831     /** 844     /** 844     /**
832      * Return a context-relative path, beginning with a "/", that represents 845      * Return a context-relative path, beginning with a "/", that represents 845      * Return a context-relative path, beginning with a "/", that represents
833      * the canonical version of the specified path after ".." and "." elements 846      * the canonical version of the specified path after ".." and "." elements 846      * the canonical version of the specified path after ".." and "." elements
834      * are resolved out.  If the specified path attempts to go outside the 847      * are resolved out.  If the specified path attempts to go outside the 847      * are resolved out.  If the specified path attempts to go outside the
835      * boundaries of the current context (i.e. too many ".." path elements 848      * boundaries of the current context (i.e. too many ".." path elements 848      * boundaries of the current context (i.e. too many ".." path elements
836      * are present), return <code>null</code> instead. 849      * are present), return <code>null</code> instead. 849      * are present), return <code>null</code> instead.
837      * 850      * 850      *
838      * @param path Path to be normalized 851      * @param path Path to be normalized 851      * @param path Path to be normalized
839      */ 852      */ 852      */
840     protected String normalize(String path) { 853     protected String normalize(String path) { 853     protected String normalize(String path) {
841  854  854 
842         if (path == null) 855         if (path == null) 855         if (path == null)
843             return null; 856             return null; 856             return null;
844  857  857 
845         // Create a place for the normalized path 858         // Create a place for the normalized path 858         // Create a place for the normalized path
846         String normalized = path; 859         String normalized = path; 859         String normalized = path;
847  860  860 
848         // Normalize "/%7E" and "/%7e" at the beginning to "/~" 861         // Normalize "/%7E" and "/%7e" at the beginning to "/~" 861         // Normalize "/%7E" and "/%7e" at the beginning to "/~"
849         if (normalized.startsWith("/%7E") || 862         if (normalized.startsWith("/%7E") || 862         if (normalized.startsWith("/%7E") ||
850             normalized.startsWith("/%7e")) 863             normalized.startsWith("/%7e")) 863             normalized.startsWith("/%7e"))
851             normalized = "/~" + normalized.substring(4); 864             normalized = "/~" + normalized.substring(4); 864             normalized = "/~" + normalized.substring(4);
852  865  865 
853         // Prevent encoding '%', '/', '.' and '\', which are special reserved 866         // Prevent encoding '%', '/', '.' and '\', which are special reserved 866         // Prevent encoding '%', '/', '.' and '\', which are special reserved
854         // characters 867         // characters 867         // characters
855         if ((normalized.indexOf("%25") >= 0) 868         if ((normalized.indexOf("%25") >= 0) 868         if ((normalized.indexOf("%25") >= 0)
856             || (normalized.indexOf("%2F") >= 0) 869             || (normalized.indexOf("%2F") >= 0) 869             || (normalized.indexOf("%2F") >= 0)
857             || (normalized.indexOf("%2E") >= 0) 870             || (normalized.indexOf("%2E") >= 0) 870             || (normalized.indexOf("%2E") >= 0)
858             || (normalized.indexOf("%5C") >= 0) 871             || (normalized.indexOf("%5C") >= 0) 871             || (normalized.indexOf("%5C") >= 0)
859             || (normalized.indexOf("%2f") >= 0) 872             || (normalized.indexOf("%2f") >= 0) 872             || (normalized.indexOf("%2f") >= 0)
860             || (normalized.indexOf("%2e") >= 0) 873             || (normalized.indexOf("%2e") >= 0) 873             || (normalized.indexOf("%2e") >= 0)
861             || (normalized.indexOf("%5c") >= 0)) { 874             || (normalized.indexOf("%5c") >= 0)) { 874             || (normalized.indexOf("%5c") >= 0)) {
862             return null; 875             return null; 875             return null;
863         } 876         } 876         }
864  877  877 
865         if (normalized.equals("/.")) 878         if (normalized.equals("/.")) 878         if (normalized.equals("/."))
866             return "/"; 879             return "/"; 879             return "/";
867  880  880 
868         // Normalize the slashes and add leading slash if necessary 881         // Normalize the slashes and add leading slash if necessary 881         // Normalize the slashes and add leading slash if necessary
869         if (normalized.indexOf('\\') >= 0) 882         if (normalized.indexOf('\\') >= 0) 882         if (normalized.indexOf('\\') >= 0)
870             normalized = normalized.replace('\\', '/'); 883             normalized = normalized.replace('\\', '/'); 883             normalized = normalized.replace('\\', '/');
871         if (!normalized.startsWith("/")) 884         if (!normalized.startsWith("/")) 884         if (!normalized.startsWith("/"))
872             normalized = "/" + normalized; 885             normalized = "/" + normalized; 885             normalized = "/" + normalized;
873  886  886 
874         // Resolve occurrences of "//" in the normalized path 887         // Resolve occurrences of "//" in the normalized path 887         // Resolve occurrences of "//" in the normalized path
875         while (true) { 888         while (true) { 888         while (true) {
876             int index = normalized.indexOf("//"); 889             int index = normalized.indexOf("//"); 889             int index = normalized.indexOf("//");
877             if (index < 0) 890             if (index < 0) 890             if (index < 0)
878                 break; 891                 break; 891                 break;
879             normalized = normalized.substring(0, index) + 892             normalized = normalized.substring(0, index) + 892             normalized = normalized.substring(0, index) +
880                 normalized.substring(index + 1); 893                 normalized.substring(index + 1); 893                 normalized.substring(index + 1);
881         } 894         } 894         }
882  895  895 
883         // Resolve occurrences of "/./" in the normalized path 896         // Resolve occurrences of "/./" in the normalized path 896         // Resolve occurrences of "/./" in the normalized path
884         while (true) { 897         while (true) { 897         while (true) {
885             int index = normalized.indexOf("/./"); 898             int index = normalized.indexOf("/./"); 898             int index = normalized.indexOf("/./");
886             if (index < 0) 899             if (index < 0) 899             if (index < 0)
887                 break; 900                 break; 900                 break;
888             normalized = normalized.substring(0, index) + 901             normalized = normalized.substring(0, index) + 901             normalized = normalized.substring(0, index) +
889                 normalized.substring(index + 2); 902                 normalized.substring(index + 2); 902                 normalized.substring(index + 2);
890         } 903         } 903         }
891  904  904 
892         // Resolve occurrences of "/../" in the normalized path 905         // Resolve occurrences of "/../" in the normalized path 905         // Resolve occurrences of "/../" in the normalized path
893         while (true) { 906         while (true) { 906         while (true) {
894             int index = normalized.indexOf("/../"); 907             int index = normalized.indexOf("/../"); 907             int index = normalized.indexOf("/../");
895             if (index < 0) 908             if (index < 0) 908             if (index < 0)
896                 break; 909                 break; 909                 break;
897             if (index == 0) 910             if (index == 0) 910             if (index == 0)
898                 return (null);  // Trying to go outside our context 911                 return (null);  // Trying to go outside our context 911                 return (null);  // Trying to go outside our context
899             int index2 = normalized.lastIndexOf('/', index - 1); 912             int index2 = normalized.lastIndexOf('/', index - 1); 912             int index2 = normalized.lastIndexOf('/', index - 1);
900             normalized = normalized.substring(0, index2) + 913             normalized = normalized.substring(0, index2) + 913             normalized = normalized.substring(0, index2) +
901                 normalized.substring(index + 3); 914                 normalized.substring(index + 3); 914                 normalized.substring(index + 3);
902         } 915         } 915         }
903  916  916 
904         // Declare occurrences of "/..." (three or more dots) to be invalid 917         // Declare occurrences of "/..." (three or more dots) to be invalid 917         // Declare occurrences of "/..." (three or more dots) to be invalid
905         // (on some Windows platforms this walks the directory tree!!!) 918         // (on some Windows platforms this walks the directory tree!!!) 918         // (on some Windows platforms this walks the directory tree!!!)
906         if (normalized.indexOf("/...") >= 0) 919         if (normalized.indexOf("/...") >= 0) 919         if (normalized.indexOf("/...") >= 0)
907             return (null); 920             return (null); 920             return (null);
908  921  921 
909         // Return the normalized path that we have completed 922         // Return the normalized path that we have completed 922         // Return the normalized path that we have completed
910         return (normalized); 923         return (normalized); 923         return (normalized);
911  924  924 
912     } 925     } 925     }
913  926  926 
914  927  927 
915     /** 928     /** 928     /**
916      * Send a confirmation that a request has been processed when pipelining. 929      * Send a confirmation that a request has been processed when pipelining. 929      * Send a confirmation that a request has been processed when pipelining.
917      * HTTP/1.1 100 Continue is sent back to the client. 930      * HTTP/1.1 100 Continue is sent back to the client. 930      * HTTP/1.1 100 Continue is sent back to the client.
918      * 931      * 931      *
919      * @param output Socket output stream 932      * @param output Socket output stream 932      * @param output Socket output stream
920      */ 933      */ 933      */
921     private void ackRequest(OutputStream output) 934     private void ackRequest(OutputStream output) 934     private void ackRequest(OutputStream output)
922         throws IOException { 935         throws IOException { 935         throws IOException {
923         if (sendAck) 936         if (sendAck) 936         if (sendAck)
924             output.write(ack); 937             output.write(ack); 937             output.write(ack);
925     } 938     } 938     }
926  939  939 
927  940  940 
928     /** 941     /** 941     /**
929      * Process an incoming HTTP request on the Socket that has been assigned 942      * Process an incoming HTTP request on the Socket that has been assigned 942      * Process an incoming HTTP request on the Socket that has been assigned
930      * to this Processor.  Any exceptions that occur during processing must be 943      * to this Processor.  Any exceptions that occur during processing must be 943      * to this Processor.  Any exceptions that occur during processing must be
931      * swallowed and dealt with. 944      * swallowed and dealt with. 944      * swallowed and dealt with.
932      * 945      * 945      *
933      * @param socket The socket on which we are connected to the client 946      * @param socket The socket on which we are connected to the client 946      * @param socket The socket on which we are connected to the client
934      */ 947      */ 947      */
935     private void process(Socket socket) { 948     private void process(Socket socket) { 948     private void process(Socket socket) {
936  949  949 
937         boolean ok = true; 950         boolean ok = true; 950         boolean ok = true;
938         boolean finishResponse = true; 951         boolean finishResponse = true; 951         boolean finishResponse = true;
939         SocketInputStream input = null; 952         SocketInputStream input = null; 952         SocketInputStream input = null;
940         OutputStream output = null; 953         OutputStream output = null; 953         OutputStream output = null;
941  954  954 
942         // Construct and initialize the objects we will need 955         // Construct and initialize the objects we will need 955         // Construct and initialize the objects we will need
943         try { 956         try { 956         try {
944             input = new SocketInputStream(socket.getInputStream(), 957             input = new SocketInputStream(socket.getInputStream(), 957             input = new SocketInputStream(socket.getInputStream(),
945                                           connector.getBufferSize()); 958                                           connector.getBufferSize()); 958                                           connector.getBufferSize());
946         } catch (Exception e) { 959         } catch (Exception e) { 959         } catch (Exception e) {
947             log("process.create", e); 960             log("process.create", e); 960             log("process.create", e);
948             ok = false; 961             ok = false; 961             ok = false;
949         } 962         } 962         }
950  963  963 
951         keepAlive = true; 964         keepAlive = true; 964         keepAlive = true;
952  965  965 
953         while (!stopped && ok && keepAlive) { 966         while (!stopped && ok && keepAlive) { 966         while (!stopped && ok && keepAlive) {
954  967  967 
955             finishResponse = true; 968             finishResponse = true; 968             finishResponse = true;
956  969  969 
957             try { 970             try { 970             try {
958                 request.setStream(input); 971                 request.setStream(input); 971                 request.setStream(input);
959                 request.setResponse(response); 972                 request.setResponse(response); 972                 request.setResponse(response);
960                 output = socket.getOutputStream(); 973                 output = socket.getOutputStream(); 973                 output = socket.getOutputStream();
961                 response.setStream(output); 974                 response.setStream(output); 974                 response.setStream(output);
962                 response.setRequest(request); 975                 response.setRequest(request); 975                 response.setRequest(request);
963                 ((HttpServletResponse) response.getResponse()).setHeader 976                 ((HttpServletResponse) response.getResponse()).setHeader 976                 ((HttpServletResponse) response.getResponse()).setHeader
964                     ("Server", Constants.ServerInfo); 977                     ("Server", 
SERVER_INFO);
 977                     ("Server", SERVER_INFO);
965             } catch (Exception e) { 978             } catch (Exception e) { 978             } catch (Exception e) {
966                 log("process.create", e); 979                 log("process.create", e); 979                 log("process.create", e);
967                 ok = false; 980                 ok = false; 980                 ok = false;
968             } 981             } 981             }
969  982  982 
970             // Parse the incoming request 983             // Parse the incoming request 983             // Parse the incoming request
971             try { 984             try { 984             try {
972                 if (ok) { 985                 if (ok) { 985                 if (ok) {
973                     parseConnection(socket); 986                     parseConnection(socket); 986                     parseConnection(socket);
974                     parseRequest(input, output); 987                     parseRequest(input, output); 987                     parseRequest(input, output);
975                     if (!request.getRequest().getProtocol() 988                     if (!request.getRequest().getProtocol() 988                     if (!request.getRequest().getProtocol()
976                         .startsWith("HTTP/0")) 989                         .startsWith("HTTP/0")) 989                         .startsWith("HTTP/0"))
977                         parseHeaders(input); 990                         parseHeaders(input); 990                         parseHeaders(input);
978                     if (http11) { 991                     if (http11) { 991                     if (http11) {
979                         // Sending a request acknowledge back to the client if 992                         // Sending a request acknowledge back to the client if 992                         // Sending a request acknowledge back to the client if
980                         // requested. 993                         // requested. 993                         // requested.
981                         ackRequest(output); 994                         ackRequest(output); 994                         ackRequest(output);
982                         // If the protocol is HTTP/1.1, chunking is allowed. 995                         // If the protocol is HTTP/1.1, chunking is allowed. 995                         // If the protocol is HTTP/1.1, chunking is allowed.
983                         if (connector.isChunkingAllowed()) 996                         if (connector.isChunkingAllowed()) 996                         if (connector.isChunkingAllowed())
984                             response.setAllowChunking(true); 997                             response.setAllowChunking(true); 997                             response.setAllowChunking(true);
985                     } 998                     } 998                     }
986                 } 999                 } 999                 }
987             } catch (EOFException e) { 1000             } catch (EOFException e) { 1000             } catch (EOFException e) {
988                 // It's very likely to be a socket disconnect on either the  1001                 // It's very likely to be a socket disconnect on either the  1001                 // It's very likely to be a socket disconnect on either the 
989                 // client or the server 1002                 // client or the server 1002                 // client or the server
990                 ok = false; 1003                 ok = false; 1003                 ok = false;
991                 finishResponse = false; 1004                 finishResponse = false; 1004                 finishResponse = false;
992             } catch (ServletException e) { 1005             } catch (ServletException e) { 1005             } catch (ServletException e) {
993                 ok = false; 1006                 ok = false; 1006                 ok = false;
994                 try { 1007                 try { 1007                 try {
995                     ((HttpServletResponse) response.getResponse()) 1008                     ((HttpServletResponse) response.getResponse()) 1008                     ((HttpServletResponse) response.getResponse())
996                         .sendError(HttpServletResponse.SC_BAD_REQUEST); 1009                         .sendError(HttpServletResponse.SC_BAD_REQUEST); 1009                         .sendError(HttpServletResponse.SC_BAD_REQUEST);
997                 } catch (Exception f) { 1010                 } catch (Exception f) { 1010                 } catch (Exception f) {
998                     ; 1011                     ; 1011                     ;
999                 } 1012                 } 1012                 }
1000             } catch (InterruptedIOException e) { 1013             } catch (InterruptedIOException e) { 1013             } catch (InterruptedIOException e) {
1001                 if (debug > 1) { 1014                 if (debug > 1) { 1014                 if (debug > 1) {
1002                     try { 1015                     try { 1015                     try {
1003                         log("process.parse", e); 1016                         log("process.parse", e); 1016                         log("process.parse", e);
1004                         ((HttpServletResponse) response.getResponse()) 1017                         ((HttpServletResponse) response.getResponse()) 1017                         ((HttpServletResponse) response.getResponse())
1005                             .sendError(HttpServletResponse.SC_BAD_REQUEST); 1018                             .sendError(HttpServletResponse.SC_BAD_REQUEST); 1018                             .sendError(HttpServletResponse.SC_BAD_REQUEST);
1006                     } catch (Exception f) { 1019                     } catch (Exception f) { 1019                     } catch (Exception f) {
1007                         ; 1020                         ; 1020                         ;
1008                     } 1021                     } 1021                     }
1009                 } 1022                 } 1022                 }
1010                 ok = false; 1023                 ok = false; 1023                 ok = false;
1011             } catch (Exception e) { 1024             } catch (Exception e) { 1024             } catch (Exception e) {
1012                 try { 1025                 try { 1025                 try {
1013                     log("process.parse", e); 1026                     log("process.parse", e); 1026                     log("process.parse", e);
1014                     ((HttpServletResponse) response.getResponse()).sendError 1027                     ((HttpServletResponse) response.getResponse()).sendError 1027                     ((HttpServletResponse) response.getResponse()).sendError
1015                         (HttpServletResponse.SC_BAD_REQUEST); 1028                         (HttpServletResponse.SC_BAD_REQUEST); 1028                         (HttpServletResponse.SC_BAD_REQUEST);
1016                 } catch (Exception f) { 1029                 } catch (Exception f) { 1029                 } catch (Exception f) {
1017                     ; 1030                     ; 1030                     ;
1018                 } 1031                 } 1031                 }
1019                 ok = false; 1032                 ok = false; 1032                 ok = false;
1020             } 1033             } 1033             }
1021  1034  1034 
1022             // Ask our Container to process this request 1035             // Ask our Container to process this request 1035             // Ask our Container to process this request
1023             try { 1036             try { 1036             try {
1024                 ((HttpServletResponse) response).addDate
Header
 1037                 ((HttpServletResponse) response).setHeader 1037                 ((HttpServletResponse) response).setHeader
1025                     ("Date", Syst
e
m
.currentTimeMillis());
 1038                     ("Date", FastHttpDateFormat.getCurrentDate
());
 1038                     ("Date", FastHttpDateFormat.getCurrentDate());
1026                 if (ok) { 1039                 if (ok) { 1039                 if (ok) {
1027                     connector.getContainer().invoke(request, response); 1040                     connector.getContainer().invoke(request, response); 1040                     connector.getContainer().invoke(request, response);
1028                 } 1041