KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > http > SocketListener


1 // ========================================================================
2
// $Id: SocketListener.java,v 1.39 2006/02/27 13:03:50 gregwilkins Exp $
3
// Copyright 199-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.http;
17 import java.io.IOException JavaDoc;
18 import java.net.Socket JavaDoc;
19 import java.net.SocketException JavaDoc;
20
21 import org.apache.commons.logging.Log;
22 import org.mortbay.log.LogFactory;
23 import org.mortbay.util.InetAddrPort;
24 import org.mortbay.util.LogSupport;
25 import org.mortbay.util.ThreadedServer;
26
27
28 /* ------------------------------------------------------------ */
29 /** Socket HTTP Listener.
30  * The behaviour of the listener can be controlled with the
31  * attributues of the ThreadedServer and ThreadPool from which it is
32  * derived. Specifically: <PRE>
33  * MinThreads - Minumum threads waiting to service requests.
34  * MaxThread - Maximum thread that will service requests.
35  * MaxIdleTimeMs - Time for an idle thread to wait for a request or read.
36  * LowResourcePersistTimeMs - time in ms that connections will persist if listener is
37  * low on resources.
38  * </PRE>
39  * @version $Id: SocketListener.java,v 1.39 2006/02/27 13:03:50 gregwilkins Exp $
40  * @author Greg Wilkins (gregw)
41  */

42 public class SocketListener
43     extends ThreadedServer
44     implements HttpListener
45 {
46     private static Log log = LogFactory.getLog(SocketListener.class);
47
48     /* ------------------------------------------------------------------- */
49     private int _lowResourcePersistTimeMs=2000;
50     private String JavaDoc _scheme=HttpMessage.__SCHEME;
51     private String JavaDoc _integralScheme=HttpMessage.__SSL_SCHEME;
52     private String JavaDoc _confidentialScheme=HttpMessage.__SSL_SCHEME;
53     private int _integralPort=0;
54     private int _confidentialPort=0;
55     private boolean _identifyListener=false;
56     private int _bufferSize=8192;
57     private int _bufferReserve=512;
58     private HttpHandler _handler;
59     private int _lowResources;
60
61     private transient HttpServer _server;
62     private transient boolean _isLow=false;
63     private transient boolean _isOut=false;
64     private transient long _warned=0;
65
66     
67     /* ------------------------------------------------------------------- */
68     public SocketListener()
69     {}
70
71     /* ------------------------------------------------------------------- */
72     public SocketListener(InetAddrPort address)
73     {
74         super(address);
75     }
76
77     /* ------------------------------------------------------------ */
78     public HttpServer getHttpServer()
79     {
80         return _server;
81     }
82     
83     /* ------------------------------------------------------------ */
84     public void setHttpServer(HttpServer server)
85     {
86         if (server!=null && _server!=null && _server!=server)
87             throw new IllegalStateException JavaDoc("Cannot share listeners");
88         _server=server;
89     }
90
91     /* ------------------------------------------------------------ */
92     public HttpHandler getHttpHandler()
93     {
94         return _handler;
95     }
96     
97     /* ------------------------------------------------------------ */
98     public void setHttpHandler(HttpHandler handler)
99     {
100         _handler=handler;
101     }
102
103     /* ------------------------------------------------------------ */
104     public int getBufferSize()
105     {
106         return _bufferSize;
107     }
108     
109     /* ------------------------------------------------------------ */
110     public void setBufferSize(int size)
111     {
112         _bufferSize=size;
113     }
114
115     /* ------------------------------------------------------------ */
116     public int getBufferReserve()
117     {
118         return _bufferReserve;
119     }
120     
121     /* ------------------------------------------------------------ */
122     public void setBufferReserve(int size)
123     {
124         _bufferReserve=size;
125     }
126         
127     /* ------------------------------------------------------------ */
128     public boolean getIdentifyListener()
129     {
130         return _identifyListener;
131     }
132     
133     /* ------------------------------------------------------------ */
134     /**
135      * @param identifyListener If true, the listener name is added to all
136      * requests as the org.mortbay.http.HttListener attribute
137      */

138     public void setIdentifyListener(boolean identifyListener)
139     {
140         _identifyListener = identifyListener;
141     }
142     
143     /* --------------------------------------------------------------- */
144     public void setDefaultScheme(String JavaDoc scheme)
145     {
146         _scheme=scheme;
147     }
148     
149     /* --------------------------------------------------------------- */
150     public String JavaDoc getDefaultScheme()
151     {
152         return _scheme;
153     }
154
155
156     /* ------------------------------------------------------------ */
157     /**
158      * @return Returns the lowResources threshold
159      */

160     public int getLowResources()
161     {
162         return _lowResources;
163     }
164     
165     /* ------------------------------------------------------------ */
166     /**
167      * @param lowResources The number of idle threads needed to not be in
168      * low resources state.
169      */

170     public void setLowResources(int lowResources)
171     {
172         _lowResources = lowResources;
173     }
174     
175     /* ------------------------------------------------------------ */
176     /**
177      * @return time in ms that connections will persist if listener is
178      * low on resources.
179      */

180     public int getLowResourcePersistTimeMs()
181     {
182         return _lowResourcePersistTimeMs;
183     }
184
185     /* ------------------------------------------------------------ */
186     /** Set the low resource persistace time.
187      * When the listener is low on resources, this timeout is used for idle
188      * persistent connections. It is desirable to have this set to a short
189      * period of time so that idle persistent connections do not consume
190      * resources on a busy server.
191      * @param ms time in ms that connections will persist if listener is
192      * low on resources.
193      */

194     public void setLowResourcePersistTimeMs(int ms)
195     {
196         _lowResourcePersistTimeMs=ms;
197     }
198     
199     
200     /* --------------------------------------------------------------- */
201     public void start()
202         throws Exception JavaDoc
203     {
204         super.start();
205         log.info("Started SocketListener on "+getInetAddrPort());
206     }
207
208     /* --------------------------------------------------------------- */
209     public void stop()
210         throws InterruptedException JavaDoc
211     {
212         super.stop();
213         log.info("Stopped SocketListener on "+getInetAddrPort());
214     }
215
216     /* ------------------------------------------------------------ */
217     /** Handle Job.
218      * Implementation of ThreadPool.handle(), calls handleConnection.
219      * @param socket A Connection.
220      */

221     public void handleConnection(Socket JavaDoc socket)
222         throws IOException JavaDoc
223     {
224         HttpConnection connection = createConnection(socket);
225         
226         try
227         {
228             if (_lowResourcePersistTimeMs>0 && isLowOnResources())
229             {
230                 socket.setSoTimeout(_lowResourcePersistTimeMs);
231                 connection.setThrottled(true);
232             }
233             else
234             {
235                 socket.setSoTimeout(getMaxIdleTimeMs());
236                 connection.setThrottled(false);
237             }
238             
239         }
240         catch(Exception JavaDoc e)
241         {
242             log.warn(LogSupport.EXCEPTION,e);
243         }
244
245         connection.handle();
246     }
247     
248     /* ------------------------------------------------------------ */
249     /** Create an HttpConnection instance. This method can be used to
250      * override the connection instance.
251      * @param socket The underlying socket.
252      */

253     protected HttpConnection createConnection(Socket JavaDoc socket)
254         throws IOException JavaDoc
255     {
256         HttpConnection c = new HttpConnection(this,
257                                   socket.getInetAddress(),
258                                   socket.getInputStream(),
259                                   socket.getOutputStream(),
260                                   socket);
261         return c;
262     }
263
264     /* ------------------------------------------------------------ */
265     /** Customize the request from connection.
266      * This method extracts the socket from the connection and calls
267      * the customizeRequest(Socket,HttpRequest) method.
268      * @param request
269      */

270     public void customizeRequest(HttpConnection connection,
271                                  HttpRequest request)
272     {
273         if (_identifyListener)
274             request.setAttribute(HttpListener.ATTRIBUTE,getName());
275         
276         Socket JavaDoc socket=(Socket JavaDoc)(connection.getConnection());
277         customizeRequest(socket,request);
278     }
279
280     /* ------------------------------------------------------------ */
281     /** Customize request from socket.
282      * Derived versions of SocketListener may specialize this method
283      * to customize the request with attributes of the socket used (eg
284      * SSL session ids).
285      * This version resets the SoTimeout if it has been reduced due to
286      * low resources. Derived implementations should call
287      * super.customizeRequest(socket,request) unless persistConnection
288      * has also been overridden and not called.
289      * @param request
290      */

291     protected void customizeRequest(Socket JavaDoc socket,
292                                     HttpRequest request)
293     {
294         try
295         {
296             if (request.getHttpConnection().isThrottled())
297             {
298                 socket.setSoTimeout(getMaxIdleTimeMs());
299                 request.getHttpConnection().setThrottled(false);
300             }
301         }
302         catch(Exception JavaDoc e)
303         {
304             LogSupport.ignore(log,e);
305         }
306     }
307
308     /* ------------------------------------------------------------ */
309     /** Persist the connection.
310      * This method is called by the HttpConnection in order to prepare a
311      * connection to be persisted. For this implementation,
312      * if the listener is low on resources, the connection read
313      * timeout is set to lowResourcePersistTimeMs. The
314      * customizeRequest method is used to reset this to the normal
315      * value after a request has been read.
316      * @param connection The HttpConnection to use.
317      */

318     public void persistConnection(HttpConnection connection)
319     {
320         try
321         {
322             Socket JavaDoc socket=(Socket JavaDoc)(connection.getConnection());
323
324             if (_lowResourcePersistTimeMs>0 && isLowOnResources())
325             {
326                 socket.setSoTimeout(_lowResourcePersistTimeMs);
327                 connection.setThrottled(true);
328             }
329             else
330                 connection.setThrottled(false);
331         }
332         catch(Exception JavaDoc e)
333         {
334             LogSupport.ignore(log,e);
335         }
336     }
337
338     /* ------------------------------------------------------------ */
339     /** Get the lowOnResource state of the listener.
340      * A SocketListener is considered low on resources if the total number of
341      * the number of idle threads is less than the lowResource value (or minThreads if not set)
342      * @return True if low on idle threads.
343      */

344     public boolean isLowOnResources()
345     {
346         int spare=getMaxThreads()-getThreads();
347         int lr = _lowResources>0?_lowResources:getMinThreads();
348         boolean low = (spare+getIdleThreads())<lr;
349         
350         if (low && !_isLow)
351         {
352             log.info("LOW ON THREADS (("+
353                       getMaxThreads()+"-"+
354                       getThreads()+"+"+
355                       getIdleThreads()+")<"+
356                       getMinThreads()+") on "+ this);
357             _warned=System.currentTimeMillis();
358             _isLow=true;
359         }
360         else if (!low && _isLow)
361         {
362             if (System.currentTimeMillis()-_warned > 1000)
363             {
364                 _isOut=false;
365                 _isLow=false;
366             }
367         }
368         return low;
369     }
370
371     /* ------------------------------------------------------------ */
372     /** Get the outOfResource state of the listener.
373      * A SocketListener is considered out of resources if the total number of
374      * threads is maxThreads and the number of idle threads is zero.
375      * @return True if out of resources.
376      */

377     public boolean isOutOfResources()
378     {
379         boolean out =
380             getThreads()==getMaxThreads() &&
381             getIdleThreads()==0;
382         
383         if (out && !_isOut)
384         {
385             log.warn("OUT OF THREADS: "+this);
386             _warned=System.currentTimeMillis();
387             _isLow=true;
388             _isOut=true;
389         }
390         
391         return out;
392     }
393     
394     /* ------------------------------------------------------------ */
395     public boolean isIntegral(HttpConnection connection)
396     {
397         return false;
398     }
399     
400     /* ------------------------------------------------------------ */
401     public boolean isConfidential(HttpConnection connection)
402     {
403         return false;
404     }
405
406     /* ------------------------------------------------------------ */
407     public String JavaDoc getIntegralScheme()
408     {
409         return _integralScheme;
410     }
411     
412     /* ------------------------------------------------------------ */
413     public void setIntegralScheme(String JavaDoc integralScheme)
414     {
415         _integralScheme = integralScheme;
416     }
417     
418     /* ------------------------------------------------------------ */
419     public int getIntegralPort()
420     {
421         return _integralPort;
422     }
423
424     /* ------------------------------------------------------------ */
425     public void setIntegralPort(int integralPort)
426     {
427         _integralPort = integralPort;
428     }
429     
430     /* ------------------------------------------------------------ */
431     public String JavaDoc getConfidentialScheme()
432     {
433         return _confidentialScheme;
434     }
435
436     /* ------------------------------------------------------------ */
437     public void setConfidentialScheme(String JavaDoc confidentialScheme)
438     {
439         _confidentialScheme = confidentialScheme;
440     }
441
442     /* ------------------------------------------------------------ */
443     public int getConfidentialPort()
444     {
445         return _confidentialPort;
446     }
447
448     /* ------------------------------------------------------------ */
449     public void setConfidentialPort(int confidentialPort)
450     {
451         _confidentialPort = confidentialPort;
452     }
453 }
454
Popular Tags