001: /*
002: * CoadunationLib: The coaduntion implementation library.
003: * Copyright (C) 2006 Rift IT Contracting
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
018: *
019: * Copyright August 26, 2006 Rift Marketing CC
020: *
021: * This class is responsible for monitoring all incoming HTTP connections and
022: * than passing of to the http request processing objects.
023: */
024:
025: // package path
026: package com.rift.coad.lib.httpd;
027:
028: // java imports
029: import java.net.ServerSocket;
030: import java.net.Socket;
031: import java.net.SocketTimeoutException;
032: import java.net.SocketException;
033:
034: // logging import
035: import org.apache.log4j.Logger;
036:
037: // jakatar imports
038: import org.apache.http.HttpServerConnection;
039: import org.apache.http.impl.DefaultHttpParams;
040: import org.apache.http.impl.DefaultHttpServerConnection;
041: import org.apache.http.params.HttpParams;
042: import org.apache.http.params.HttpProtocolParams;
043: import org.apache.http.params.HttpConnectionParams;
044: import org.apache.http.protocol.ResponseContent;
045: import org.apache.http.protocol.ResponseDate;
046: import org.apache.http.protocol.ResponseServer;
047: import org.apache.http.protocol.ResponseConnControl;
048:
049: // coadunation imports
050: import com.rift.coad.lib.thread.BasicThread;
051: import com.rift.coad.lib.thread.ThreadStateMonitor;
052: import com.rift.coad.lib.configuration.ConfigurationFactory;
053: import com.rift.coad.lib.configuration.Configuration;
054: import com.rift.coad.lib.security.ThreadsPermissionContainer;
055:
056: /**
057: * This class is responsible for monitoring all incoming HTTP connections and
058: * than passing of to the http request processing objects.
059: *
060: * @author Brett Chaldecott
061: */
062: public class RequestListenerThread extends BasicThread {
063:
064: // class constants
065: public final static String HTTP_HOST = "http_host";
066: public final static String HTTP_PORT = "http_port";
067: private final static String SOCKET_TIMEOUT = "socket_timeout";
068: private final static int DEFAULT_SOCKET_TIMEOUT = 500;
069: private final static String HTTP_TIMEOUT = "http_timeout";
070: private final static int DEFAULT_HTTP_TIMEOUT = 5000;
071: private final static String HTTP_BUFFER_SIZE = "http_buffer_size";
072: private final static int DEFAULT_BUFFER_SIZE = 8;
073: private final static String ORIGIN_SERVER = "Coadunation-WebServices/1.1";
074: private final static String DOCUMENT_ROOT_PARAM = "server.docroot";
075: private final static String HTTP_DOCUMENT_ROOT_CONFIG = "server_doc_root";
076: private final static String HTTP_SECURITY_REALM = "realm";
077: private final static String DEFAULT_HTTP_SECURITY_REALM = "coadunation";
078:
079: // the class log variable
080: protected Logger log = Logger.getLogger(RequestListenerThread.class
081: .getName());
082:
083: // the private member variables
084: private ThreadStateMonitor monitor = new ThreadStateMonitor();
085: private HttpRequestManager httpRequestManager = null;
086: private ServerSocket serversocket = null;
087: private HttpParams params = null;
088: private String securityRealm = null;
089:
090: /**
091: * Creates a new instance of RequestListenerThread
092: *
093: *
094: * @param httpRequestManager The request manager.
095: * @exception HHttpdException
096: */
097: public RequestListenerThread(HttpRequestManager httpRequestManager)
098: throws HttpdException, Exception {
099: try {
100: this .httpRequestManager = httpRequestManager;
101: Configuration config = ConfigurationFactory.getInstance()
102: .getConfig(this .getClass());
103:
104: // init the server socket
105: this .serversocket = new ServerSocket((int) config.getLong(
106: HTTP_PORT, HttpDaemon.DEFAULT_PORT));
107:
108: // setup the parameters
109: this .params = new DefaultHttpParams(null);
110:
111: // retrieve the http timeout
112: int timeout = (int) config.getLong(HTTP_TIMEOUT,
113: DEFAULT_HTTP_TIMEOUT);
114:
115: // retrieve the buffer size in kilo bytes
116: int kBufferSize = (int) config.getLong(HTTP_BUFFER_SIZE,
117: DEFAULT_BUFFER_SIZE);
118:
119: // the realm
120: securityRealm = config.getString(HTTP_SECURITY_REALM,
121: DEFAULT_HTTP_SECURITY_REALM);
122:
123: // set the parameters
124: this .params
125: .setIntParameter(HttpConnectionParams.SO_TIMEOUT,
126: timeout)
127: .setIntParameter(
128: HttpConnectionParams.SOCKET_BUFFER_SIZE,
129: kBufferSize * 1024)
130: .setBooleanParameter(
131: HttpConnectionParams.STALE_CONNECTION_CHECK,
132: false).setBooleanParameter(
133: HttpConnectionParams.TCP_NODELAY, true)
134: .setParameter(HttpProtocolParams.ORIGIN_SERVER,
135: ORIGIN_SERVER).setParameter(
136: "server.docroot", "/");
137: } catch (Exception ex) {
138: throw new HttpdException(
139: "Failed to start the request listerner thread : "
140: + ex.getMessage(), ex);
141: }
142:
143: }
144:
145: /**
146: * This method replaces the run method in the BasicThread.
147: *
148: * @exception Exception
149: */
150: public void process() throws Exception {
151: while (monitor.isTerminated() == false) {
152: try {
153: log.debug("Wait for a socket connection");
154: Socket socket = this .serversocket.accept();
155: HttpServerConnection conn = new DefaultHttpServerConnection();
156: log.debug("Process request from : "
157: + socket.getInetAddress());
158: conn.bind(socket, this .params);
159: HttpServiceHandler httpServiceHandler = new HttpServiceHandler(
160: conn, socket, securityRealm);
161:
162: // Required protocol interceptors
163: httpServiceHandler.addInterceptor(new ResponseDate());
164: httpServiceHandler.addInterceptor(new ResponseServer());
165: httpServiceHandler
166: .addInterceptor(new ResponseContent());
167: httpServiceHandler
168: .addInterceptor(new ResponseConnControl());
169: httpServiceHandler.setParams(this .params);
170:
171: // add the object to the queue for processing
172: log.debug("Add a request to the queue");
173: httpRequestManager.addRequest(httpServiceHandler);
174:
175: } catch (SocketTimeoutException ex) {
176: // ignore the time out we do not want to block in definitly
177: } catch (SocketException ex) {
178: if (!serversocket.isClosed()) {
179: log.error("Failed to process an http request : "
180: + ex.getMessage(), ex);
181: }
182: } catch (Exception ex) {
183: log.error("Failed to process an http request : "
184: + ex.getMessage(), ex);
185: }
186: }
187: }
188:
189: /**
190: * This method will be implemented by child objects to terminate the
191: * processing of this thread.
192: */
193: public void terminate() {
194: try {
195: serversocket.close();
196: } catch (Exception ex) {
197: log.error(
198: "Failed to close the socket : " + ex.getMessage(),
199: ex);
200: }
201: monitor.terminate(false);
202: }
203:
204: }
|