18. Araxis Merge File Comparison Report

Produced by Araxis Merge on 2016-08-05 08:07:12 +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.

18.1 Files compared

#LocationFileLast Modified
1/Merge Test Files/jakarta-tomcat-4.0.6-src/catalina/src/share/org/apache/catalina/connector/http10HttpProcessor.java2002-10-08 14:15:34 +0000
2/Merge Test Files/jakarta-tomcat-4.1.18-src/catalina/src/share/org/apache/catalina/connector/http10HttpProcessor.java2002-12-19 13:49:40 +0000

18.2 Comparison summary

DescriptionBetween
Files 1 and 2
Text BlocksLines
Unchanged71820
Changed311
Inserted322
Removed00

18.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

18.4 Active regular expressions

No regular expressions were active.

18.5 Comparison detail

1 /* 1 /*
2  * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/HttpProcessor.java,v 1.4.2.2 2002/04/04 17:46:09 remm Exp $ 2  * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/http10/HttpProcessor.java,v 1.9 2002/04/04 17:50:34 remm Exp $
3  * $Revision: 1.4.2.2 $ 3  * $Revision: 1.9 $
4  * $Date: 2002/04/04 17:46:09 $ 4  * $Date: 2002/04/04 17:50:34 $
5  * 5  *
6  * ==================================================================== 6  * ====================================================================
7  * 7  *
8  * The Apache Software License, Version 1.1 8  * The Apache Software License, Version 1.1
9  * 9  *
10  * Copyright (c) 1999 The Apache Software Foundation.  All rights 10  * Copyright (c) 1999 The Apache Software Foundation.  All rights
11  * reserved. 11  * reserved.
12  * 12  *
13  * Redistribution and use in source and binary forms, with or without 13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions 14  * modification, are permitted provided that the following conditions
15  * are met: 15  * are met:
16  * 16  *
17  * 1. Redistributions of source code must retain the above copyright 17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer. 18  *    notice, this list of conditions and the following disclaimer.
19  * 19  *
20  * 2. Redistributions in binary form must reproduce the above copyright 20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in 21  *    notice, this list of conditions and the following disclaimer in
22  *    the documentation and/or other materials provided with the 22  *    the documentation and/or other materials provided with the
23  *    distribution. 23  *    distribution.
24  * 24  *
25  * 3. The end-user documentation included with the redistribution, if 25  * 3. The end-user documentation included with the redistribution, if
26  *    any, must include the following acknowlegement: 26  *    any, must include the following acknowlegement:
27  *       "This product includes software developed by the 27  *       "This product includes software developed by the
28  *        Apache Software Foundation (http://www.apache.org/)." 28  *        Apache Software Foundation (http://www.apache.org/)."
29  *    Alternately, this acknowlegement may appear in the software itself, 29  *    Alternately, this acknowlegement may appear in the software itself,
30  *    if and wherever such third-party acknowlegements normally appear. 30  *    if and wherever such third-party acknowlegements normally appear.
31  * 31  *
32  * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software 32  * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
33  *    Foundation" must not be used to endorse or promote products derived 33  *    Foundation" must not be used to endorse or promote products derived
34  *    from this software without prior written permission. For written 34  *    from this software without prior written permission. For written
35  *    permission, please contact apache@apache.org. 35  *    permission, please contact apache@apache.org.
36  * 36  *
37  * 5. Products derived from this software may not be called "Apache" 37  * 5. Products derived from this software may not be called "Apache"
38  *    nor may "Apache" appear in their names without prior written 38  *    nor may "Apache" appear in their names without prior written
39  *    permission of the Apache Group. 39  *    permission of the Apache Group.
40  * 40  *
41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 44  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 47  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 48  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 49  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE. 52  * SUCH DAMAGE.
53  * ==================================================================== 53  * ====================================================================
54  * 54  *
55  * This software consists of voluntary contributions made by many 55  * This software consists of voluntary contributions made by many
56  * individuals on behalf of the Apache Software Foundation.  For more 56  * individuals on behalf of the Apache Software Foundation.  For more
57  * information on the Apache Software Foundation, please see 57  * information on the Apache Software Foundation, please see
58  * <http://www.apache.org/>. 58  * <http://www.apache.org/>.
59  * 59  *
60  * [Additional notices, if required by prior licensing conditions] 60  * [Additional notices, if required by prior licensing conditions]
61  * 61  *
62  */ 62  */
63  63 
64  64 
65 package org.apache.catalina.connector.http10; 65 package org.apache.catalina.connector.http10;
66  66 
67  67 
68 import java.io.BufferedInputStream; 68 import java.io.BufferedInputStream;
69 import java.io.InputStream; 69 import java.io.InputStream;
70 import java.io.IOException; 70 import java.io.IOException;
71 import java.io.OutputStream; 71 import java.io.OutputStream;
72 import java.net.InetAddress; 72 import java.net.InetAddress;
73 import java.net.Socket; 73 import java.net.Socket;
74 import java.util.NoSuchElementException; 74 import java.util.NoSuchElementException;
75 import java.util.StringTokenizer; 75 import java.util.StringTokenizer;
76 import java.util.Locale; 76 import java.util.Locale;
77 import java.util.Hashtable; 77 import java.util.Hashtable;
78 import java.util.Vector; 78 import java.util.Vector;
79 import java.util.Enumeration; 79 import java.util.Enumeration;
80 import javax.servlet.ServletException; 80 import javax.servlet.ServletException;
81 import javax.servlet.http.Cookie; 81 import javax.servlet.http.Cookie;
82 import javax.servlet.http.HttpServletRequest; 82 import javax.servlet.http.HttpServletRequest;
83 import javax.servlet.http.HttpServletResponse; 83 import javax.servlet.http.HttpServletResponse;
84 import org.apache.catalina.Connector; 84 import org.apache.catalina.Connector;
85 import org.apache.catalina.Container; 85 import org.apache.catalina.Container;
86 import org.apache.catalina.Globals; 86 import org.apache.catalina.Globals;
87 import org.apache.catalina.HttpRequest; 87 import org.apache.catalina.HttpRequest;
88 import org.apache.catalina.HttpResponse; 88 import org.apache.catalina.HttpResponse;
89 import org.apache.catalina.Lifecycle; 89 import org.apache.catalina.Lifecycle;
90 import org.apache.catalina.LifecycleEvent; 90 import org.apache.catalina.LifecycleEvent;
91 import org.apache.catalina.LifecycleException; 91 import org.apache.catalina.LifecycleException;
92 import org.apache.catalina.LifecycleListener; 92 import org.apache.catalina.LifecycleListener;
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.RequestUtil;
95 import org.apache.catalina.util.LifecycleSupport; 95 import org.apache.catalina.util.LifecycleSupport;
    96 import org.apache.catalina.util.ServerInfo;
96 import org.apache.catalina.util.StringManager; 97 import org.apache.catalina.util.StringManager;
97  98 
98  99 
99 /** 100 /**
100  * Implementation of a request processor (and its associated thread) that may 101  * Implementation of a request processor (and its associated thread) that may
101  * be used by an HttpConnector to process individual requests.  The connector 102  * be used by an HttpConnector to process individual requests.  The connector
102  * will allocate a processor from its pool, assign a particular socket to it, 103  * will allocate a processor from its pool, assign a particular socket to it,
103  * and the processor will then execute the processing required to complete 104  * and the processor will then execute the processing required to complete
104  * the request.  When the processor is completed, it will recycle itself. 105  * the request.  When the processor is completed, it will recycle itself.
105  * 106  *
106  * @author Craig R. McClanahan 107  * @author Craig R. McClanahan
107  * @version $Revision: 1.4.2.2 $ $Date: 2002/04/04 17:46:09 $ 108  * @version $Revision: 1.9 $ $Date: 2002/04/04 17:50:34 $
    109  * @deprecated
108  */ 110  */
109  111 
110 final class HttpProcessor 112 final class HttpProcessor
111     implements Lifecycle, Runnable { 113     implements Lifecycle, Runnable {
112  114 
113  115 
    116     // ----------------------------------------------------- Manifest Constants
    117 
    118 
    119     /**
    120      * Server information string for this server.
    121      */
    122     private static final String SERVER_INFO =
    123         ServerInfo.getServerInfo() + " (HTTP/1.0 Connector)";
    124 
    125 
114     // ----------------------------------------------------------- Constructors 126     // ----------------------------------------------------------- Constructors
115  127 
116  128 
117     /** 129     /**
118      * Construct a new HttpProcessor associated with the specified connector. 130      * Construct a new HttpProcessor associated with the specified connector.
119      * 131      *
120      * @param connector HttpConnector that owns this processor 132      * @param connector HttpConnector that owns this processor
121      * @param id Identifier of this HttpProcessor (unique per connector) 133      * @param id Identifier of this HttpProcessor (unique per connector)
122      */ 134      */
123     public HttpProcessor(HttpConnector connector, int id) { 135     public HttpProcessor(HttpConnector connector, int id) {
124  136 
125         super(); 137         super();
126         this.connector = connector; 138         this.connector = connector;
127         this.debug = connector.getDebug(); 139         this.debug = connector.getDebug();
128         this.id = id; 140         this.id = id;
129         this.proxyName = connector.getProxyName(); 141         this.proxyName = connector.getProxyName();
130         this.proxyPort = connector.getProxyPort(); 142         this.proxyPort = connector.getProxyPort();
131         this.request = (HttpRequestImpl) connector.createRequest(); 143         this.request = (HttpRequestImpl) connector.createRequest();
132         this.response = (HttpResponseImpl) connector.createResponse(); 144         this.response = (HttpResponseImpl) connector.createResponse();
133         this.serverPort = connector.getPort(); 145         this.serverPort = connector.getPort();
134         this.threadName = 146         this.threadName =
135           "HttpProcessor[" + connector.getPort() + "][" + id + "]"; 147           "HttpProcessor[" + connector.getPort() + "][" + id + "]";
136  148 
137     } 149     }
138  150 
139  151 
140     // ----------------------------------------------------- Instance Variables 152     // ----------------------------------------------------- Instance Variables
141  153 
142  154 
143     /** 155     /**
144      * Is there a new socket available? 156      * Is there a new socket available?
145      */ 157      */
146     private boolean available = false; 158     private boolean available = false;
147  159 
148  160 
149     /** 161     /**
150      * The HttpConnector with which this processor is associated. 162      * The HttpConnector with which this processor is associated.
151      */ 163      */
152     private HttpConnector connector = null; 164     private HttpConnector connector = null;
153  165 
154  166 
155     /** 167     /**
156      * The debugging detail level for this component. 168      * The debugging detail level for this component.
157      */ 169      */
158     private int debug = 0; 170     private int debug = 0;
159  171 
160  172 
161     /** 173     /**
162      * The identifier of this processor, unique per connector. 174      * The identifier of this processor, unique per connector.
163      */ 175      */
164     private int id = 0; 176     private int id = 0;
165  177 
166  178 
167     /** 179     /**
168      * The lifecycle event support for this component. 180      * The lifecycle event support for this component.
169      */ 181      */
170     private LifecycleSupport lifecycle = new LifecycleSupport(this); 182     private LifecycleSupport lifecycle = new LifecycleSupport(this);
171  183 
172  184 
173     /** 185     /**
174      * The match string for identifying a session ID parameter. 186      * The match string for identifying a session ID parameter.
175      */ 187      */
176     private static final String match = 188     private static final String match =
177         ";" + Globals.SESSION_PARAMETER_NAME + "="; 189         ";" + Globals.SESSION_PARAMETER_NAME + "=";
178  190 
179  191 
180     /** 192     /**
181      * The proxy server name for our Connector. 193      * The proxy server name for our Connector.
182      */ 194      */
183     private String proxyName = null; 195     private String proxyName = null;
184  196 
185  197 
186     /** 198     /**
187      * The proxy server port for our Connector. 199      * The proxy server port for our Connector.
188      */ 200      */
189     private int proxyPort = 0; 201     private int proxyPort = 0;
190  202 
191  203 
192     /** 204     /**
193      * The HTTP request object we will pass to our associated container. 205      * The HTTP request object we will pass to our associated container.
194      */ 206      */
195     private HttpRequestImpl request = null; 207     private HttpRequestImpl request = null;
196  208 
197  209 
198     /** 210     /**
199      * The HTTP response object we will pass to our associated container. 211      * The HTTP response object we will pass to our associated container.
200      */ 212      */
201     private HttpResponseImpl response = null; 213     private HttpResponseImpl response = null;
202  214 
203  215 
204     /** 216     /**
205      * The actual server port for our Connector. 217      * The actual server port for our Connector.
206      */ 218      */
207     private int serverPort = 0; 219     private int serverPort = 0;
208  220 
209  221 
210     /** 222     /**
211      * The string manager for this package. 223      * The string manager for this package.
212      */ 224      */
213     protected StringManager sm = 225     protected StringManager sm =
214         StringManager.getManager(Constants.Package); 226         StringManager.getManager(Constants.Package);
215  227 
216  228 
217     /** 229     /**
218      * The socket we are currently processing a request for.  This object 230      * The socket we are currently processing a request for.  This object
219      * is used for inter-thread communication only. 231      * is used for inter-thread communication only.
220      */ 232      */
221     private Socket socket = null; 233     private Socket socket = null;
222  234 
223  235 
224     /** 236     /**
225      * Has this component been started yet? 237      * Has this component been started yet?
226      */ 238      */
227     private boolean started = false; 239     private boolean started = false;
228  240 
229  241 
230     /** 242     /**
231      * The shutdown signal to our background thread 243      * The shutdown signal to our background thread
232      */ 244      */
233     private boolean stopped = false; 245     private boolean stopped = false;
234  246 
235  247 
236     /** 248     /**
237      * The background thread. 249      * The background thread.
238      */ 250      */
239     private Thread thread = null; 251     private Thread thread = null;
240  252 
241  253 
242     /** 254     /**
243      * The name to register for the background thread. 255      * The name to register for the background thread.
244      */ 256      */
245     private String threadName = null; 257     private String threadName = null;
246  258 
247  259 
248     /** 260     /**
249      * The thread synchronization object. 261      * The thread synchronization object.
250      */ 262      */
251     private Object threadSync = new Object(); 263     private Object threadSync = new Object();
252  264 
253  265 
254     // -------------------------------------------------------- Package Methods 266     // -------------------------------------------------------- Package Methods
255  267 
256  268 
257     /** 269     /**
258      * Process an incoming TCP/IP connection on the specified socket.  Any 270      * Process an incoming TCP/IP connection on the specified socket.  Any
259      * exception that occurs during processing must be logged and swallowed. 271      * exception that occurs during processing must be logged and swallowed.
260      * <b>NOTE</b>:  This method is called from our Connector's thread.  We 272      * <b>NOTE</b>:  This method is called from our Connector's thread.  We
261      * must assign it to our own thread so that multiple simultaneous 273      * must assign it to our own thread so that multiple simultaneous
262      * requests can be handled. 274      * requests can be handled.
263      * 275      *
264      * @param socket TCP socket to process 276      * @param socket TCP socket to process
265      */ 277      */
266     synchronized void assign(Socket socket) { 278     synchronized void assign(Socket socket) {
267  279 
268         // Wait for the Processor to get the previous Socket 280         // Wait for the Processor to get the previous Socket
269         while (available) { 281         while (available) {
270             try { 282             try {
271                 wait(); 283                 wait();
272             } catch (InterruptedException e) { 284             } catch (InterruptedException e) {
273             } 285             }
274         } 286         }
275  287 
276         // Store the newly available Socket and notify our thread 288         // Store the newly available Socket and notify our thread
277         this.socket = socket; 289         this.socket = socket;
278         available = true; 290         available = true;
279         notifyAll(); 291         notifyAll();
280  292 
281         if ((debug >= 1) && (socket != null)) 293         if ((debug >= 1) && (socket != null))
282             log(" An incoming request is being assigned"); 294             log(" An incoming request is being assigned");
283  295 
284     } 296     }
285  297 
286  298 
287     // -------------------------------------------------------- Private Methods 299     // -------------------------------------------------------- Private Methods
288  300 
289  301 
290     /** 302     /**
291      * Await a newly assigned Socket from our Connector, or <code>null</code> 303      * Await a newly assigned Socket from our Connector, or <code>null</code>
292      * if we are supposed to shut down. 304      * if we are supposed to shut down.
293      */ 305      */
294     private synchronized Socket await() { 306     private synchronized Socket await() {
295  307 
296         // Wait for the Connector to provide a new Socket 308         // Wait for the Connector to provide a new Socket
297         while (!available) { 309         while (!available) {
298             try { 310             try {
299                 wait(); 311                 wait();
300             } catch (InterruptedException e) { 312             } catch (InterruptedException e) {
301             } 313             }
302         } 314         }
303  315 
304         // Notify the Connector that we have received this Socket 316         // Notify the Connector that we have received this Socket
305         Socket socket = this.socket; 317         Socket socket = this.socket;
306         available = false; 318         available = false;
307         notifyAll(); 319         notifyAll();
308  320 
309         if ((debug >= 1) && (socket != null)) 321         if ((debug >= 1) && (socket != null))
310             log("  The incoming request has been awaited"); 322             log("  The incoming request has been awaited");
311  323 
312         return (socket); 324         return (socket);
313  325 
314     } 326     }
315  327 
316  328 
317  329 
318     /** 330     /**
319      * Log a message on the Logger associated with our Container (if any) 331      * Log a message on the Logger associated with our Container (if any)
320      * 332      *
321      * @param message Message to be logged 333      * @param message Message to be logged
322      */ 334      */
323     private void log(String message) { 335     private void log(String message) {
324  336 
325         Logger logger = connector.getContainer().getLogger(); 337         Logger logger = connector.getContainer().getLogger();
326         if (logger != null) 338         if (logger != null)
327             logger.log(threadName + " " + message); 339             logger.log(threadName + " " + message);
328  340 
329     } 341     }
330  342 
331  343 
332     /** 344     /**
333      * Log a message on the Logger associated with our Container (if any) 345      * Log a message on the Logger associated with our Container (if any)
334      * 346      *
335      * @param message Message to be logged 347      * @param message Message to be logged
336      * @param throwable Associated exception 348      * @param throwable Associated exception
337      */ 349      */
338     private void log(String message, Throwable throwable) { 350     private void log(String message, Throwable throwable) {
339  351 
340         Logger logger = connector.getContainer().getLogger(); 352         Logger logger = connector.getContainer().getLogger();
341         if (logger != null) 353         if (logger != null)
342             logger.log(threadName + " " + message, throwable); 354             logger.log(threadName + " " + message, throwable);
343  355 
344     } 356     }
345  357 
346  358 
347     /** 359     /**
348      * Parse and record the connection parameters related to this request. 360      * Parse and record the connection parameters related to this request.
349      * 361      *
350      * @param socket The socket on which we are connected 362      * @param socket The socket on which we are connected
351      * 363      *
352      * @exception IOException if an input/output error occurs 364      * @exception IOException if an input/output error occurs
353      * @exception ServletException if a parsing error occurs 365      * @exception ServletException if a parsing error occurs
354      */ 366      */
355     private void parseConnection(Socket socket) 367     private void parseConnection(Socket socket)
356         throws IOException, ServletException { 368         throws IOException, ServletException {
357  369 
358         if (debug >= 2) 370         if (debug >= 2)
359             log("  parseConnection: address=" + socket.getInetAddress() + 371             log("  parseConnection: address=" + socket.getInetAddress() +
360                 ", port=" + connector.getPort()); 372                 ", port=" + connector.getPort());
361         ((HttpRequestImpl) request).setInet(socket.getInetAddress()); 373         ((HttpRequestImpl) request).setInet(socket.getInetAddress());
362         if (proxyPort != 0) 374         if (proxyPort != 0)
363             request.setServerPort(proxyPort); 375             request.setServerPort(proxyPort);
364         else 376         else
365             request.setServerPort(serverPort); 377             request.setServerPort(serverPort);
366         request.setSocket(socket); 378         request.setSocket(socket);
367  379 
368     } 380     }
369  381 
370  382 
371     /** 383     /**
372      * Parse the incoming HTTP request headers, and set the appropriate 384      * Parse the incoming HTTP request headers, and set the appropriate
373      * request headers. 385      * request headers.
374      * 386      *
375      * @param input The input stream connected to our socket 387      * @param input The input stream connected to our socket
376      * 388      *
377      * @exception IOException if an input/output error occurs 389      * @exception IOException if an input/output error occurs
378      * @exception ServletException if a parsing error occurs 390      * @exception ServletException if a parsing error occurs
379      */ 391      */
380     private void parseHeaders(InputStream input) 392     private void parseHeaders(InputStream input)
381         throws IOException, ServletException { 393         throws IOException, ServletException {
382  394 
383         while (true) { 395         while (true) {
384  396 
385             // Read the next header line 397             // Read the next header line
386             String line = read(input); 398             String line = read(input);
387             if ((line == null) || (line.length() < 1)) 399             if ((line == null) || (line.length() < 1))
388                 break; 400                 break;
389  401 
390             // Parse the header name and value 402             // Parse the header name and value
391             int colon = line.indexOf(':'); 403             int colon = line.indexOf(':');
392             if (colon < 0) 404             if (colon < 0)
393                 throw new ServletException 405                 throw new ServletException
394                     (sm.getString("httpProcessor.parseHeaders.colon")); 406                     (sm.getString("httpProcessor.parseHeaders.colon"));
395             String name = line.substring(0, colon).trim(); 407             String name = line.substring(0, colon).trim();
396             String match = name.toLowerCase(); 408             String match = name.toLowerCase();
397             String value = line.substring(colon + 1).trim(); 409             String value = line.substring(colon + 1).trim();
398             if (debug >= 1) 410             if (debug >= 1)
399                 log(" Header " + name + " = " + value); 411                 log(" Header " + name + " = " + value);
400  412 
401             // Set the corresponding request headers 413             // Set the corresponding request headers
402             if (match.equals("authorization")) { 414             if (match.equals("authorization")) {
403                 request.setAuthorization(value); 415                 request.setAuthorization(value);
404                 request.addHeader(name, value); 416                 request.addHeader(name, value);
405             } else if (match.equals("accept-language")) { 417             } else if (match.equals("accept-language")) {
406           request.addHeader(name, value); 418           request.addHeader(name, value);
407           // 419           //
408           // Adapted from old code perhaps maybe optimized 420           // Adapted from old code perhaps maybe optimized
409           // 421           //
410           // 422           //
411           Hashtable languages = new Hashtable(); 423           Hashtable languages = new Hashtable();
412           StringTokenizer languageTokenizer = new StringTokenizer(value, ","); 424           StringTokenizer languageTokenizer = new StringTokenizer(value, ",");
413  425 
414           while (languageTokenizer.hasMoreTokens()) { 426           while (languageTokenizer.hasMoreTokens()) {
415             String language = languageTokenizer.nextToken().trim(); 427             String language = languageTokenizer.nextToken().trim();
416             int qValueIndex = language.indexOf(';'); 428             int qValueIndex = language.indexOf(';');
417             int qIndex = language.indexOf('q'); 429             int qIndex = language.indexOf('q');
418             int equalIndex = language.indexOf('='); 430             int equalIndex = language.indexOf('=');
419             Double qValue = new Double(1); 431             Double qValue = new Double(1);
420  432 
421             if (qValueIndex > -1 && qValueIndex < qIndex && qIndex < equalIndex) { 433             if (qValueIndex > -1 && qValueIndex < qIndex && qIndex < equalIndex) {
422               String qValueStr = language.substring(qValueIndex + 1); 434               String qValueStr = language.substring(qValueIndex + 1);
423               language = language.substring(0, qValueIndex); 435               language = language.substring(0, qValueIndex);
424               qValueStr = qValueStr.trim().toLowerCase(); 436               qValueStr = qValueStr.trim().toLowerCase();
425               qValueIndex = qValueStr.indexOf('='); 437               qValueIndex = qValueStr.indexOf('=');
426               qValue = new Double(0); 438               qValue = new Double(0);
427               if (qValueStr.startsWith("q") && 439               if (qValueStr.startsWith("q") &&
428                   qValueIndex > -1) { 440                   qValueIndex > -1) {
429                   qValueStr = qValueStr.substring(qValueIndex + 1); 441                   qValueStr = qValueStr.substring(qValueIndex + 1);
430                   try { 442                   try {
431                       qValue = new Double(qValueStr.trim()); 443                       qValue = new Double(qValueStr.trim());
432                   } catch (NumberFormatException nfe) { 444                   } catch (NumberFormatException nfe) {
433                   } 445                   }
434               } 446               }
435             } 447             }
436             // XXX 448             // XXX
437             // may need to handle "*" at some point in time 449             // may need to handle "*" at some point in time
438             if (! language.equals("*")) { 450             if (! language.equals("*")) {
439                 String key = qValue.toString(); 451                 String key = qValue.toString();
440                 Vector v = (Vector)((languages.containsKey(key)) ? languages.get(key) : new Vector()); 452                 Vector v = (Vector)((languages.containsKey(key)) ? languages.get(key) : new Vector());
441                 v.addElement(language); 453                 v.addElement(language);
442                 languages.put(key, v); 454                 languages.put(key, v);
443             } 455             }
444           } 456           }
445           Vector l = new Vector(); 457           Vector l = new Vector();
446           Enumeration e = languages.keys(); 458           Enumeration e = languages.keys();
447           while (e.hasMoreElements()) { 459           while (e.hasMoreElements()) {
448               String key = (String)e.nextElement(); 460               String key = (String)e.nextElement();
449               Vector v = (Vector)languages.get(key); 461               Vector v = (Vector)languages.get(key);
450               Enumeration le = v.elements(); 462               Enumeration le = v.elements();
451               while (le.hasMoreElements()) { 463               while (le.hasMoreElements()) {
452                 String language = (String)le.nextElement(); 464                 String language = (String)le.nextElement();
453                 String country = ""; 465                 String country = "";
454                 String variant = ""; 466                 String variant = "";
455                 int countryIndex = language.indexOf('-'); 467                 int countryIndex = language.indexOf('-');
456                 if (countryIndex > -1) { 468                 if (countryIndex > -1) {
457                     country = language.substring(countryIndex + 1).trim(); 469                     country = language.substring(countryIndex + 1).trim();
458                     language = language.substring(0, countryIndex).trim(); 470                     language = language.substring(0, countryIndex).trim();
459                     int vDash = country.indexOf("-"); 471                     int vDash = country.indexOf("-");
460                     if (vDash > 0) { 472                     if (vDash > 0) {
461                         String cTemp = country.substring(0, vDash); 473                         String cTemp = country.substring(0, vDash);
462                         variant = country.substring(vDash + 1); 474                         variant = country.substring(vDash + 1);
463                         country = cTemp; 475                         country = cTemp;
464                      476                     
465                 } 477                 }
466                 request.addLocale(new Locale(language, country, variant)); 478                 request.addLocale(new Locale(language, country, variant));
467               } 479               }
468           } 480           }
469             } else if (match.equals("cookie")) { 481             } else if (match.equals("cookie")) {
470                 Cookie cookies[] = RequestUtil.parseCookieHeader(value); 482                 Cookie cookies[] = RequestUtil.parseCookieHeader(value);
471                 for (int i = 0; i < cookies.length; i++) { 483                 for (int i = 0; i < cookies.length; i++) {
472                     if (cookies[i].getName().equals 484                     if (cookies[i].getName().equals
473                         (Globals.SESSION_COOKIE_NAME)) { 485                         (Globals.SESSION_COOKIE_NAME)) {
474                         // Override anything requested in the URL 486                         // Override anything requested in the URL
475                         if (!request.isRequestedSessionIdFromCookie()) { 487                         if (!request.isRequestedSessionIdFromCookie()) {
476                             // Accept only the first session id cookie 488                             // Accept only the first session id cookie
477                             request.setRequestedSessionId 489                             request.setRequestedSessionId
478                                 (cookies[i].getValue()); 490                                 (cookies[i].getValue());
479                             request.setRequestedSessionCookie(true); 491                             request.setRequestedSessionCookie(true);
480                             request.setRequestedSessionURL(false); 492                             request.setRequestedSessionURL(false);
481                             if (debug >= 1) 493                             if (debug >= 1)
482                                 log(" Requested cookie session id is " + 494                                 log(" Requested cookie session id is " +
483                                     ((HttpServletRequest) request.getRequest()) 495                                     ((HttpServletRequest) request.getRequest())
484                                     .getRequestedSessionId()); 496                                     .getRequestedSessionId());
485                         } 497                         }
486                     } 498                     }
487                     request.addCookie(cookies[i]); 499                     request.addCookie(cookies[i]);
488                 } 500                 }
489                 // Keep Watchdog from whining by adding the header as well 501                 // Keep Watchdog from whining by adding the header as well
490                 // (GetHeaderTest, GetIntHeader_1Test) 502                 // (GetHeaderTest, GetIntHeader_1Test)
491                 request.addHeader(name, value); 503                 request.addHeader(name, value);
492             } else if (match.equals("content-length")) { 504             } else if (match.equals("content-length")) {
493                 int n = -1; 505                 int n = -1;
494                 try { 506                 try {
495                     n = Integer.parseInt(value); 507                     n = Integer.parseInt(value);
496                 } catch (Exception e) { 508                 } catch (Exception e) {
497                     throw new ServletException 509                     throw new ServletException
498                         (sm.getString("httpProcessor.parseHeaders.contentLength")); 510                         (sm.getString("httpProcessor.parseHeaders.contentLength"));
499                 } 511                 }
500                 request.setContentLength(n); 512                 request.setContentLength(n);
501                 request.addHeader(name, value); 513                 request.addHeader(name, value);
502             } else if (match.equals("content-type")) { 514             } else if (match.equals("content-type")) {
503                 request.setContentType(value); 515                 request.setContentType(value);
504                 request.addHeader(name, value); 516                 request.addHeader(name, value);
505             } else if (match.equals("host")) { 517             } else if (match.equals("host")) {
506                 int n = value.indexOf(':'); 518                 int n = value.indexOf(':');
507                 if (n < 0) 519                 if (n < 0)
508                     request.setServerName(value); 520                     request.setServerName(value);
509                 else { 521                 else {
510                     request.setServerName(value.substring(0, n).trim()); 522                     request.setServerName(value.substring(0, n).trim());
511                     int port = 80; 523                     int port = 80;
512                     try { 524                     try {
513                         port = Integer.parseInt(value.substring(n+1).trim()); 525                         port = Integer.parseInt(value.substring(n+1).trim());
514                     } catch (Exception e) { 526                     } catch (Exception e) {
515                         throw new ServletException 527                         throw new ServletException
516                             (sm.getString("httpProcessor.parseHeaders.portNumber")); 528                             (sm.getString("httpProcessor.parseHeaders.portNumber"));
517                     } 529                     }
518                     request.setServerPort(port); 530                     request.setServerPort(port);
519                 } 531                 }
520                 request.addHeader(name, value); 532                 request.addHeader(name, value);
521             } else { 533             } else {
522                 request.addHeader(name, value); 534                 request.addHeader(name, value);
523             } 535             }
524         } 536         }
525  537 
526     } 538     }
527  539 
528  540 
529     /** 541     /**
530      * Parse the incoming HTTP request and set the corresponding HTTP request 542      * Parse the incoming HTTP request and set the corresponding HTTP request
531      * properties. 543      * properties.
532      * 544      *
533      * @param input The input stream attached to our socket 545      * @param input The input stream attached to our socket
534      * 546      *
535      * @exception IOException if an input/output error occurs 547      * @exception IOException if an input/output error occurs
536      * @exception ServletException if a parsing error occurs 548      * @exception ServletException if a parsing error occurs
537      */ 549      */
538     private void parseRequest(InputStream input) 550     private void parseRequest(InputStream input)
539         throws IOException, ServletException { 551         throws IOException, ServletException {
540  552 
541         // Parse the incoming request line 553         // Parse the incoming request line
542         String line = read(input); 554         String line = read(input);
543         if (line == null) 555         if (line == null)
544             throw new ServletException 556             throw new ServletException
545                 (sm.getString("httpProcessor.parseRequest.read")); 557                 (sm.getString("httpProcessor.parseRequest.read"));
546         StringTokenizer st = new StringTokenizer(line); 558         StringTokenizer st = new StringTokenizer(line);
547  559 
548         String method = null; 560         String method = null;
549         try { 561         try {
550             method = st.nextToken(); 562             method = st.nextToken();
551         } catch (NoSuchElementException e) { 563         } catch (NoSuchElementException e) {
552             method = null; 564             method = null;
553         } 565         }
554  566 
555         String uri = null; 567         String uri = null;
556         try { 568         try {
557             uri = st.nextToken(); 569             uri = st.nextToken();
558             ;   // FIXME - URL decode the URI? 570             ;   // FIXME - URL decode the URI?
559         } catch (NoSuchElementException e) { 571         } catch (NoSuchElementException e) {
560             uri = null; 572             uri = null;
561         } 573         }
562  574 
563         String protocol = null; 575         String protocol = null;
564         try { 576         try {
565             protocol = st.nextToken(); 577             protocol = st.nextToken();
566         } catch (NoSuchElementException e) { 578         } catch (NoSuchElementException e) {
567             protocol = "HTTP/0.9"; 579             protocol = "HTTP/0.9";
568         } 580         }
569  581 
570         // Validate the incoming request line 582         // Validate the incoming request line
571         if (method == null) { 583         if (method == null) {
572             throw new ServletException 584             throw new ServletException
573                 (sm.getString("httpProcessor.parseRequest.method")); 585                 (sm.getString("httpProcessor.parseRequest.method"));
574         } else if (uri == null) { 586         } else if (uri == null) {
575             throw new ServletException 587             throw new ServletException
576                 (sm.getString("httpProcessor.parseRequest.uri")); 588                 (sm.getString("httpProcessor.parseRequest.uri"));
577         } 589         }
578  590 
579         // Parse any query parameters out of the request URI 591         // Parse any query parameters out of the request URI
580         int question = uri.indexOf('?'); 592         int question = uri.indexOf('?');
581         if (question >= 0) { 593         if (question >= 0) {
582             request.setQueryString(uri.substring(question + 1)); 594             request.setQueryString(uri.substring(question + 1));
583             if (debug >= 1) 595             if (debug >= 1)
584                 log(" Query string is " + 596                 log(" Query string is " +
585                     ((HttpServletRequest) request.getRequest()).getQueryString()); 597                     ((HttpServletRequest) request.getRequest()).getQueryString());
586             uri = uri.substring(0, question); 598             uri = uri.substring(0, question);
587         } else 599         } else
588             request.setQueryString(null); 600             request.setQueryString(null);
589  601 
590         // Parse any requested session ID out of the request URI 602         // Parse any requested session ID out of the request URI
591         int semicolon = uri.indexOf(match); 603         int semicolon = uri.indexOf(match);
592         if (semicolon >= 0) { 604         if (semicolon >= 0) {
593             String rest = uri.substring(semicolon + match.length()); 605             String rest = uri.substring(semicolon + match.length());
594             int semicolon2 = rest.indexOf(';'); 606             int semicolon2 = rest.indexOf(';');
595             if (semicolon2 >= 0) { 607             if (semicolon2 >= 0) {
596                 request.setRequestedSessionId(rest.substring(0, semicolon2)); 608                 request.setRequestedSessionId(rest.substring(0, semicolon2));
597                 rest = rest.substring(semicolon2); 609                 rest = rest.substring(semicolon2);
598             } else { 610             } else {
599                 request.setRequestedSessionId(rest); 611                 request.setRequestedSessionId(rest);
600                 rest = ""; 612                 rest = "";
601             } 613             }
602             request.setRequestedSessionURL(true); 614             request.setRequestedSessionURL(true);
603             uri = uri.substring(0, semicolon) + rest; 615             uri = uri.substring(0, semicolon) + rest;
604             if (debug >= 1) 616             if (debug >= 1)
605                 log(" Requested URL session id is " + 617                 log(" Requested URL session id is " +
606                     ((HttpServletRequest) request.getRequest()).getRequestedSessionId()); 618                     ((HttpServletRequest) request.getRequest()).getRequestedSessionId());
607         } else { 619         } else {
608             request.setRequestedSessionId(null); 620             request.setRequestedSessionId(null);
609             request.setRequestedSessionURL(false); 621             request.setRequestedSessionURL(false);
610         } 622         }
611  623 
612         // Set the corresponding request properties 624         // Set the corresponding request properties
613         ((HttpRequest) request).setMethod(method); 625         ((HttpRequest) request).setMethod(method);
614         request.setProtocol(protocol); 626         request.setProtocol(protocol);
615         ((HttpRequest) request).setRequestURI(uri); 627         ((HttpRequest) request).setRequestURI(uri);
616         request.setSecure(false);       // No SSL support 628         request.setSecure(false);       // No SSL support
617         request.setScheme("http");      // No SSL support 629         request.setScheme("http");      // No SSL support
618  630 
619         if (debug >= 1) 631         if (debug >= 1)
620             log(" Request is " + method + " for " + uri); 632             log(" Request is " + method + " for " + uri);
621  633 
622     } 634     }
623  635 
624  636 
625     /** 637     /**
626      * Process an incoming HTTP request on the Socket that has been assigned 638      * Process an incoming HTTP request on the Socket that has been assigned
627      * to this Processor.  Any exceptions that occur during processing must be 639      * to this Processor.  Any exceptions that occur during processing must be
628      * swallowed and dealt with. 640      * swallowed and dealt with.
629      * 641      *
630      * @param socket The socket on which we are connected to the client 642      * @param socket The socket on which we are connected to the client
631      */ 643      */
632     private void process(Socket socket) { 644     private void process(Socket socket) {
633  645 
634         boolean ok = true; 646         boolean ok = true;
635         InputStream input = null; 647         InputStream input = null;
636         OutputStream output = null; 648         OutputStream output = null;
637  649 
638         // Construct and initialize the objects we will need 650         // Construct and initialize the objects we will need
639         try { 651         try {
640             input = new BufferedInputStream(socket.getInputStream(), 652             input = new BufferedInputStream(socket.getInputStream(),
641                                             connector.getBufferSize()); 653                                             connector.getBufferSize());
642             request.setStream(input); 654             request.setStream(input);
643             request.setResponse(response); 655             request.setResponse(response);
644             output = socket.getOutputStream(); 656             output = socket.getOutputStream();
645             response.setStream(output); 657             response.setStream(output);
646             response.setRequest(request); 658             response.setRequest(request);
647             ((HttpServletResponse) response.getResponse()).setHeader 659             ((HttpServletResponse) response.getResponse()).setHeader
648                 ("Server", Constants.ServerInfo); 660                 ("Server", 
SERVER_INFO);
649         } catch (Exception e) { 661         } catch (Exception e) {
650             log("process.create", e); 662             log("process.create", e);
651             ok = false; 663             ok = false;
652         } 664         }
653  665 
654         // Parse the incoming request 666         // Parse the incoming request
655         try { 667         try {
656             if (ok) { 668             if (ok) {
657                 parseConnection(socket); 669                 parseConnection(socket);
658                 parseRequest(input); 670                 parseRequest(input);
659                 if (!request.getRequest().getProtocol().startsWith("HTTP/0")) 671                 if (!request.getRequest().getProtocol().startsWith("HTTP/0"))
660                     parseHeaders(input); 672                     parseHeaders(input);
661             } 673             }
662         } catch (Exception e) { 674         } catch (Exception e) {
663             try { 675             try {
664                 log("process.parse", e); 676                 log("process.parse", e);
665                 ((HttpServletResponse) response.getResponse()).sendError 677                 ((HttpServletResponse) response.getResponse()).sendError
666                     (HttpServletResponse.SC_BAD_REQUEST); 678                     (HttpServletResponse.SC_BAD_REQUEST);
667             } catch (Exception f) { 679             } catch (Exception f) {
668                 ; 680                 ;
669             } 681             }
670         } 682         }
671  683 
672         // Ask our Container to process this request 684         // Ask our Container to process this request
673         try { 685         try {
674             if (ok) { 686             if (ok) {
675                 connector.getContainer().invoke(request, response); 687                 connector.getContainer().invoke(request, response);
676             } 688             }
677         } catch (ServletException e) { 689         } catch (ServletException e) {
678             log("process.invoke", e); 690             log("process.invoke", e);
679             try { 691             try {
680                 ((HttpServletResponse) response.getResponse()).sendError 692                 ((HttpServletResponse) response.getResponse()).sendError
681                     (HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 693                     (HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
682             } catch (Exception f) { 694             } catch (Exception f) {
683                 ; 695                 ;
684             } 696             }
685             ok = false; 697             ok = false;
686         } catch (Throwable e) { 698         } catch (Throwable e) {
687             log("process.invoke", e); 699             log("process.invoke", e);
688             try { 700             try {
689                 ((HttpServletResponse) response.getResponse()).sendError 701                 ((HttpServletResponse) response.getResponse()).sendError
690                     (HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 702                     (HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
691             } catch (Exception f) { 703             } catch (Exception f) {
692                 ; 704                 ;
693             } 705             }
694             ok = false; 706             ok = false;
695         } 707         }
696  708 
697         // Finish up the handling of the response 709         // Finish up the handling of the response
698         try { 710         try {
699             if (ok) 711             if (ok)
700                 response.finishResponse(); 712                 response.finishResponse();
701         } catch (IOException e) { 713         } catch (IOException e) {
702             log("FIXME-Exception from finishResponse", e); 714             log("FIXME-Exception from finishResponse", e);
703         } 715         }
704         try { 716         try {
705             if (output != null) 717             if (output != null)
706                 output.flush(); 718                 output.flush();
707         } catch (IOException e) { 719         } catch (IOException e) {
708             log("FIXME-Exception flushing output", e); 720             log("FIXME-Exception flushing output", e);
709         } 721         }
710         try { 722         try {
711             if (output != null) 723             if (output != null)
712                 output.close(); 724                 output.close();
713         } catch (IOException e) { 725         } catch (IOException e) {
714             log("FIXME-Exception closing output", e); 726             log("FIXME-Exception closing output", e);
715         } 727         }
716  728 
717         // Finish up the handling of the request 729         // Finish up the handling of the request
718         try { 730         try {
719             if (ok) 731             if (ok)
720                 request.finishRequest(); 732                 request.finishRequest();
721         } catch (IOException e) { 733         } catch (IOException e) {
722             log("FIXME-Exception from finishRequest", e); 734             log("FIXME-Exception from finishRequest", e);
723         } 735         }
724         try { 736         try {
725             if (input != null) 737             if (input != null)
726                 input.close(); 738                 input.close();
727         } catch (IOException e) { 739         } catch (IOException e) {
728             log("FIXME-Exception closing input", e); 740             log("FIXME-Exception closing input", e);
729         } 741         }
730  742 
731         // Finish up the handling of the socket connection itself 743         // Finish up the handling of the socket connection itself
732         try { 744         try {
733             socket.close(); 745             socket.close();
734         } catch (IOException e) { 746         } catch (IOException e) {
735             log("FIXME-Exception closing socket", e); 747             log("FIXME-Exception closing socket", e);
736         } 748         }
737         socket = null; 749         socket = null;
738  750 
739     } 751     }
740  752 
741  753 
742     /** 754     /**
743      * Read a line from the specified input stream, and strip off the 755      * Read a line from the specified input stream, and strip off the
744      * trailing carriage return and newline (if any).  Return the remaining 756      * trailing carriage return and newline (if any).  Return the remaining
745      * characters that were read as a String. 757      * characters that were read as a String.
746      * 758      *
747      * @param input The input stream connected to our socket 759      * @param input The input stream connected to our socket
748      * 760      *
749      * @returns The line that was read, or <code>null</code> if end-of-file 761      * @returns The line that was read, or <code>null</code> if end-of-file
750      *  was encountered 762      *  was encountered
751      * 763      *
752      * @exception IOException if an input/output error occurs 764      * @exception IOException if an input/output error occurs
753      */ 765      */
754     private String read(InputStream input) throws IOException { 766     private String read(InputStream input) throws IOException {
755  767 
756         StringBuffer sb = new StringBuffer(); 768         StringBuffer sb = new StringBuffer();
757         while (true) { 769         while (true) {
758             int ch = input.read(); 770             int ch = input.read();
759             if (ch < 0) { 771             if (ch < 0) {
760                 if (sb.length() == 0) { 772                 if (sb.length() == 0) {
761                     return (null); 773                     return (null);
762                 } else { 774                 } else {
763                     break; 775                     break;
764                 } 776                 }
765             } else if (ch == '\r') { 777             } else if (ch == '\r') {
766                 continue; 778                 continue;
767             } else if (ch == '\n') { 779             } else if (ch == '\n') {
768                 break; 780                 break;
769             } 781             }
770             sb.append((char) ch); 782             sb.append((char) ch);
771         } 783         }
772         if (debug >= 2) 784         if (debug >= 2)
773             log("  Read: " + sb.toString()); 785             log("  Read: " + sb.toString());
774         return (sb.toString()); 786         return (sb.toString());
775  787 
776     } 788     }
777  789 
778  790 
779     // ---------------------------------------------- Background Thread Methods 791     // ---------------------------------------------- Background Thread Methods
780  792 
781  793 
782     /** 794     /**
783      * The background thread that listens for incoming TCP/IP connections and 795      * The background thread that listens for incoming TCP/IP connections and
784      * hands them off to an appropriate processor. 796      * hands them off to an appropriate processor.
785      */ 797      */
786     public void run() { 798     public void run() {
787  799 
788         // Process requests until we receive a shutdown signal 800         // Process requests until we receive a shutdown signal
789         while (!stopped) { 801         while (!stopped) {
790  802 
791             // Wait for the next socket to be assigned 803             // Wait for the next socket to be assigned
792             Socket socket = await(); 804             Socket socket = await();
793             if (socket == null) 805             if (socket == null)
794                 continue; 806                 continue;
795  807 
796             // Process the request from this socket 808             // Process the request from this socket
797             process(socket); 809             process(socket);
798  810 
799             // Finish up this request 811             // Finish up this request
800             request.recycle(); 812             request.recycle();
801             response.recycle(); 813             response.recycle();
802             connector.recycle(this); 814             connector.recycle(this);
803  815 
804         } 816         }
805  817 
806         // Tell threadStop() we have shut ourselves down successfully 818         // Tell threadStop() we have shut ourselves down successfully
807         synchronized (threadSync) { 819         synchronized (threadSync) {
808             threadSync.notifyAll(); 820             threadSync.notifyAll();
809         } 821         }
810  822 
811     } 823     }
812  824 
813  825 
814     /** 826     /**
815      * Start the background processing thread. 827      * Start the background processing thread.
816      */ 828      */
817     private void threadStart() { 829     private void threadStart() {
818  830 
819         log(sm.getString("httpProcessor.starting")); 831         log(sm.getString("httpProcessor.starting"));
820  832 
821         thread = new Thread(this, threadName); 833         thread = new Thread(this, threadName);
822         thread.setDaemon(true); 834         thread.setDaemon(true);
823         thread.start(); 835         thread.start();
824  836 
825         if (debug >= 1) 837         if (debug >= 1)
826             log(" Background thread has been started"); 838             log(" Background thread has been started");
827  839 
828     } 840     }
829  841 
830  842 
831     /** 843     /**
832      * Stop the background processing thread. 844      * Stop the background processing thread.
833      */ 845      */
834     private void threadStop() { 846     private void threadStop() {
835  847 
836         log(sm.getString("httpProcessor.stopping")); 848         log(sm.getString("httpProcessor.stopping"));
837  849 
838         stopped = true; 850         stopped = true;
839         assign(null); 851         assign(null);
840         synchronized (threadSync) { 852         synchronized (threadSync) {
841             try { 853             try {
842                 threadSync.wait(5000); 854                 threadSync.wait(5000);
843             } catch (InterruptedException e) { 855             } catch (InterruptedException e) {
844                 ; 856                 ;
845             } 857             }
846         } 858         }
847         thread = null; 859         thread = null;
848  860 
849     } 861     }
850  862 
851  863 
852     // ------------------------------------------------------ Lifecycle Methods 864     // ------------------------------------------------------ Lifecycle Methods
853  865 
854  866 
855     /** 867     /**
856      * Add a lifecycle event listener to this component. 868      * Add a lifecycle event listener to this component.
857      * 869      *
858      * @param listener The listener to add 870      * @param listener The listener to add
859      */ 871      */
860     public void addLifecycleListener(LifecycleListener listener) { 872     public void addLifecycleListener(LifecycleListener listener) {
861  873 
862         lifecycle.addLifecycleListener(listener); 874         lifecycle.addLifecycleListener(listener);
863  875 
864     } 876     }
865  877 
866  878 
867     /** 879     /**
    880      * Get the lifecycle listeners associated with this lifecycle. If this 
    881      * Lifecycle has no listeners registered, a zero-length array is returned.
    882      */
    883     public LifecycleListener[] findLifecycleListeners() {
    884 
    885         return lifecycle.findLifecycleListeners();
    886 
    887     }
    888 
    889 
    890     /**
868      * Remove a lifecycle event listener from this component. 891      * Remove a lifecycle event listener from this component.
869      * 892      *
870      * @param listener The listener to add 893      * @param listener The listener to add
871      */ 894      */
872     public void removeLifecycleListener(LifecycleListener listener) { 895     public void removeLifecycleListener(LifecycleListener listener) {
873  896 
874         lifecycle.removeLifecycleListener(listener); 897         lifecycle.removeLifecycleListener(listener);
875  898 
876     } 899     }
877  900 
878  901 
879     /** 902     /**
880      * Start the background thread we will use for request processing. 903      * Start the background thread we will use for request processing.
881      * 904      *
882      * @exception LifecycleException if a fatal startup error occurs 905      * @exception LifecycleException if a fatal startup error occurs
883      */ 906      */
884     public void start() throws LifecycleException { 907     public void start() throws LifecycleException {
885  908 
886         if (started) 909         if (started)
887             throw new LifecycleException 910             throw new LifecycleException
888                 (sm.getString("httpProcessor.alreadyStarted")); 911                 (sm.getString("httpProcessor.alreadyStarted"));
889         lifecycle.fireLifecycleEvent(START_EVENT, null); 912         lifecycle.fireLifecycleEvent(START_EVENT, null);
890         started = true; 913         started = true;
891  914 
892         threadStart(); 915         threadStart();
893  916 
894     } 917     }
895  918 
896  919 
897     /** 920     /**
898      * Stop the background thread we will use for request processing. 921      * Stop the background thread we will use for request processing.
899      * 922      *
900      * @exception LifecycleException if a fatal shutdown error occurs 923      * @exception LifecycleException if a fatal shutdown error occurs
901      */ 924      */
902     public void stop() throws LifecycleException { 925     public void stop() throws LifecycleException {
903  926 
904         if (!started) 927         if (!started)
905             throw new LifecycleException 928             throw new LifecycleException
906                 (sm.getString("httpProcessor.notStarted")); 929                 (sm.getString("httpProcessor.notStarted"));
907         lifecycle.fireLifecycleEvent(STOP_EVENT, null); 930         lifecycle.fireLifecycleEvent(STOP_EVENT, null);
908         started = false; 931         started = false;
909  932 
910         threadStop(); 933         threadStop();
911  934 
912     } 935     }
913  936 
914  937 
915 } 938 }