Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/mortbay/http/SocketListener.java


1   // ========================================================================
2   // Copyright (c) 1999-2002 Mort Bay Consulting (Australia) Pty. Ltd.
3   // $Id: SocketListener.java,v 1.33 2003/11/22 16:06:02 gregwilkins Exp $
4   // ========================================================================
5   
6   package org.mortbay.http;
7   import java.io.IOException;
8   import java.net.Socket;
9   
10  import org.apache.commons.logging.Log;
11  import org.apache.commons.logging.LogFactory;
12  import org.mortbay.util.InetAddrPort;
13  import org.mortbay.util.LogSupport;
14  import org.mortbay.util.ThreadedServer;
15  
16  
17  /* ------------------------------------------------------------ */
18  /** Socket HTTP Listener.
19   * The behaviour of the listener can be controlled with the
20   * attributues of the ThreadedServer and ThreadPool from which it is
21   * derived. Specifically: <PRE>
22   * MinThreads    - Minumum threads waiting to service requests.
23   * MaxThread     - Maximum thread that will service requests.
24   * MaxIdleTimeMs - Time for an idle thread to wait for a request or read.
25   * LowResourcePersistTimeMs - time in ms that connections will persist if listener is
26   *                            low on resources. 
27   * </PRE>
28   * @version $Id: SocketListener.java,v 1.33 2003/11/22 16:06:02 gregwilkins Exp $
29   * @author Greg Wilkins (gregw)
30   */
31  public class SocketListener
32      extends ThreadedServer
33      implements HttpListener
34  {
35      private static Log log = LogFactory.getLog(SocketListener.class);
36  
37      /* ------------------------------------------------------------------- */
38      private int _lowResourcePersistTimeMs=2000;
39      private String _scheme=HttpMessage.__SCHEME;
40      private String _integralScheme=HttpMessage.__SSL_SCHEME;
41      private String _confidentialScheme=HttpMessage.__SSL_SCHEME;
42      private int _integralPort=0;
43      private int _confidentialPort=0;
44      private boolean _identifyListener=false;
45      private int _bufferSize=8192;
46      private int _bufferReserve=512;
47      private HttpHandler _handler;
48  
49      private transient HttpServer _server;
50      private transient boolean _isLow=false;
51      private transient boolean _isOut=false;
52      private transient long _warned=0;
53      
54      /* ------------------------------------------------------------------- */
55      public SocketListener()
56      {}
57  
58      /* ------------------------------------------------------------------- */
59      public SocketListener(InetAddrPort address)
60      {
61          super(address);
62      }
63  
64      /* ------------------------------------------------------------ */
65      public HttpServer getHttpServer()
66      {
67          return _server;
68      }
69      
70      /* ------------------------------------------------------------ */
71      public void setHttpServer(HttpServer server)
72      {
73          if (server!=null && _server!=null && _server!=server)
74              throw new IllegalStateException("Cannot share listeners");
75          _server=server;
76      }
77  
78      /* ------------------------------------------------------------ */
79      public HttpHandler getHttpHandler()
80      {
81          return _handler;
82      }
83      
84      /* ------------------------------------------------------------ */
85      public void setHttpHandler(HttpHandler handler)
86      {
87          _handler=handler;
88      }
89  
90      /* ------------------------------------------------------------ */
91      public int getBufferSize()
92      {
93          return _bufferSize;
94      }
95      
96      /* ------------------------------------------------------------ */
97      public void setBufferSize(int size)
98      {
99          _bufferSize=size;
100     }
101 
102     /* ------------------------------------------------------------ */
103     public int getBufferReserve()
104     {
105         return _bufferReserve;
106     }
107     
108     /* ------------------------------------------------------------ */
109     public void setBufferReserve(int size)
110     {
111         _bufferReserve=size;
112     }
113         
114     /* ------------------------------------------------------------ */
115     public boolean getIdentifyListener()
116     {
117         return _identifyListener;
118     }
119     
120     /* ------------------------------------------------------------ */
121     /** 
122      * @param identifyListener If true, the listener name is added to all
123      * requests as the org.mortbay.http.HttListener attribute
124      */
125     public void setIdentifyListener(boolean identifyListener)
126     {
127         _identifyListener = identifyListener;
128     }
129     
130     /* --------------------------------------------------------------- */
131     public void setDefaultScheme(String scheme)
132     {
133         _scheme=scheme;
134     }
135     
136     /* --------------------------------------------------------------- */
137     public String getDefaultScheme()
138     {
139         return _scheme;
140     }
141 
142     /* ------------------------------------------------------------ */
143     /** 
144      * @return time in ms that connections will persist if listener is
145      * low on resources.
146      */
147     public int getLowResourcePersistTimeMs()
148     {
149         return _lowResourcePersistTimeMs;
150     }
151 
152     /* ------------------------------------------------------------ */
153     /** Set the low resource persistace time.
154      * When the listener is low on resources, this timeout is used for idle
155      * persistent connections.  It is desirable to have this set to a short
156      * period of time so that idle persistent connections do not consume
157      * resources on a busy server.
158      * @param ms time in ms that connections will persist if listener is
159      * low on resources. 
160      */
161     public void setLowResourcePersistTimeMs(int ms)
162     {
163         _lowResourcePersistTimeMs=ms;
164     }
165     
166     
167     /* --------------------------------------------------------------- */
168     public void start()
169         throws Exception
170     {
171         super.start();
172         log.info("Started SocketListener on "+getInetAddrPort());
173     }
174 
175     /* --------------------------------------------------------------- */
176     public void stop()
177         throws InterruptedException
178     {
179         super.stop();
180         log.info("Stopped SocketListener on "+getInetAddrPort());
181     }
182 
183     /* ------------------------------------------------------------ */
184     /** Handle Job.
185      * Implementation of ThreadPool.handle(), calls handleConnection.
186      * @param socket A Connection.
187      */
188     public void handleConnection(Socket socket)
189         throws IOException
190     {
191         HttpConnection connection = createConnection(socket);
192         
193         try
194         {
195             if (_lowResourcePersistTimeMs>0 && isLowOnResources())
196             {
197                 socket.setSoTimeout(_lowResourcePersistTimeMs);
198                 connection.setThrottled(true);
199             }
200             else
201             {
202                 socket.setSoTimeout(getMaxIdleTimeMs());
203                 connection.setThrottled(false);
204             }
205             
206         }
207         catch(Exception e)
208         {
209             log.warn(LogSupport.EXCEPTION,e);
210         }
211 
212         connection.handle();
213     }
214     
215     /* ------------------------------------------------------------ */
216     /** Create an HttpConnection instance. This method can be used to
217      * override the connection instance.
218      * @param socket The underlying socket.
219      */
220     protected HttpConnection createConnection(Socket socket)
221         throws IOException
222     {
223         return new HttpConnection(this,
224                                   socket.getInetAddress(),
225                                   socket.getInputStream(),
226                                   socket.getOutputStream(),
227                                   socket);
228     }
229 
230     /* ------------------------------------------------------------ */
231     /** Customize the request from connection.
232      * This method extracts the socket from the connection and calls
233      * the customizeRequest(Socket,HttpRequest) method.
234      * @param request
235      */
236     public void customizeRequest(HttpConnection connection,
237                                  HttpRequest request)
238     {
239         if (_identifyListener)
240             request.setAttribute(HttpListener.ATTRIBUTE,getName());
241         
242         Socket socket=(Socket)(connection.getConnection());
243         customizeRequest(socket,request);
244     }
245 
246     /* ------------------------------------------------------------ */
247     /** Customize request from socket.
248      * Derived versions of SocketListener may specialize this method
249      * to customize the request with attributes of the socket used (eg
250      * SSL session ids).
251      * This version resets the SoTimeout if it has been reduced due to
252      * low resources.  Derived implementations should call
253      * super.customizeRequest(socket,request) unless persistConnection
254      * has also been overridden and not called.
255      * @param request
256      */
257     protected void customizeRequest(Socket socket,
258                                     HttpRequest request)
259     {
260         try
261         {
262             if (request.getHttpConnection().isThrottled())
263             {
264                 socket.setSoTimeout(getMaxIdleTimeMs());
265                 request.getHttpConnection().setThrottled(false);
266             }
267         }
268         catch(Exception e)
269         {
270             LogSupport.ignore(log,e);
271         }
272     }
273 
274     /* ------------------------------------------------------------ */
275     /** Persist the connection.
276      * This method is called by the HttpConnection in order to prepare a
277      * connection to be persisted. For this implementation,
278      * if the listener is low on resources, the connection read
279      * timeout is set to lowResourcePersistTimeMs.  The
280      * customizeRequest method is used to reset this to the normal
281      * value after a request has been read.
282      * @param connection The HttpConnection to use.
283      */
284     public void persistConnection(HttpConnection connection)
285     {
286         try
287         {
288             Socket socket=(Socket)(connection.getConnection());
289 
290             if (_lowResourcePersistTimeMs>0 && isLowOnResources())
291             {
292                 socket.setSoTimeout(_lowResourcePersistTimeMs);
293                 connection.setThrottled(true);
294             }
295             else
296                 connection.setThrottled(false);
297         }
298         catch(Exception e)
299         {
300             LogSupport.ignore(log,e);
301         }
302     }
303 
304     /* ------------------------------------------------------------ */
305     /** Get the lowOnResource state of the listener.
306      * A SocketListener is considered low on resources if the total number of
307      * threads is maxThreads and the number of idle threads is less than minThreads.
308      * @return True if low on idle threads. 
309      */
310     public boolean isLowOnResources()
311     {
312         boolean low =
313             getThreads()==getMaxThreads() &&
314             getIdleThreads()<getMinThreads();
315         
316         if (low && !_isLow)
317         {
318             log.info("LOW ON THREADS: "+this);
319             _warned=System.currentTimeMillis();
320             _isLow=true;
321         }
322         else if (!low && _isLow)
323         {
324             if (System.currentTimeMillis()-_warned > 1000)
325             {
326                 _isOut=false;
327                 _isLow=false;
328             }
329         }
330         return low;
331     }
332 
333     /* ------------------------------------------------------------ */
334     /**  Get the outOfResource state of the listener.
335      * A SocketListener is considered out of resources if the total number of
336      * threads is maxThreads and the number of idle threads is zero.
337      * @return True if out of resources. 
338      */
339     public boolean isOutOfResources()
340     {
341         boolean out =
342             getThreads()==getMaxThreads() &&
343             getIdleThreads()==0;
344         
345         if (out && !_isOut)
346         {
347             log.warn("OUT OF THREADS: "+this);
348             _warned=System.currentTimeMillis();
349             _isOut=true;
350         }
351         
352         return out;
353     }
354     
355     /* ------------------------------------------------------------ */
356     public boolean isIntegral(HttpConnection connection)
357     {
358         return false;
359     }
360     
361     /* ------------------------------------------------------------ */
362     public boolean isConfidential(HttpConnection connection)
363     {
364         return false;
365     }
366 
367     /* ------------------------------------------------------------ */
368     public String getIntegralScheme()
369     {
370         return _integralScheme;
371     }
372     
373     /* ------------------------------------------------------------ */
374     public void setIntegralScheme(String integralScheme)
375     {
376         _integralScheme = integralScheme;
377     }
378     
379     /* ------------------------------------------------------------ */
380     public int getIntegralPort()
381     {
382         return _integralPort;
383     }
384 
385     /* ------------------------------------------------------------ */
386     public void setIntegralPort(int integralPort)
387     {
388         _integralPort = integralPort;
389     }
390     
391     /* ------------------------------------------------------------ */
392     public String getConfidentialScheme()
393     {
394         return _confidentialScheme;
395     }
396 
397     /* ------------------------------------------------------------ */
398     public void setConfidentialScheme(String confidentialScheme)
399     {
400         _confidentialScheme = confidentialScheme;
401     }
402 
403     /* ------------------------------------------------------------ */
404     public int getConfidentialPort()
405     {
406         return _confidentialPort;
407     }
408 
409     /* ------------------------------------------------------------ */
410     public void setConfidentialPort(int confidentialPort)
411     {
412         _confidentialPort = confidentialPort;
413     }
414     
415 }