001: /*
002: * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/server/SimpleHttpServer.java,v 1.15 2004/12/11 22:35:26 olegk Exp $
003: * $Revision: 480424 $
004: * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
005: *
006: * ====================================================================
007: *
008: * Licensed to the Apache Software Foundation (ASF) under one or more
009: * contributor license agreements. See the NOTICE file distributed with
010: * this work for additional information regarding copyright ownership.
011: * The ASF licenses this file to You under the Apache License, Version 2.0
012: * (the "License"); you may not use this file except in compliance with
013: * the License. You may obtain a copy of the License at
014: *
015: * http://www.apache.org/licenses/LICENSE-2.0
016: *
017: * Unless required by applicable law or agreed to in writing, software
018: * distributed under the License is distributed on an "AS IS" BASIS,
019: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
020: * See the License for the specific language governing permissions and
021: * limitations under the License.
022: * ====================================================================
023: *
024: * This software consists of voluntary contributions made by many
025: * individuals on behalf of the Apache Software Foundation. For more
026: * information on the Apache Software Foundation, please see
027: * <http://www.apache.org/>.
028: *
029: */
030:
031: package org.apache.commons.httpclient.server;
032:
033: import java.io.IOException;
034: import java.net.InetAddress;
035: import java.net.ServerSocket;
036: import java.net.Socket;
037:
038: import org.apache.commons.logging.Log;
039: import org.apache.commons.logging.LogFactory;
040:
041: /**
042: * A simple, but extensible HTTP server, mostly for testing purposes.
043: *
044: * @author Christian Kohlschuetter
045: * @author Oleg Kalnichevski
046: */
047: public class SimpleHttpServer implements Runnable {
048: private static final Log LOG = LogFactory
049: .getLog(SimpleHttpServer.class);
050:
051: private String testname = "Simple test";
052: private long count = 0;
053: private ServerSocket listener = null;
054: private Thread t;
055: private ThreadGroup tg;
056: private boolean stopped = false;
057:
058: private SimpleConnSet connections = new SimpleConnSet();
059:
060: private HttpRequestHandler requestHandler = null;
061:
062: /**
063: * Creates a new HTTP server instance, using an arbitrary free TCP port
064: *
065: * @throws IOException if anything goes wrong during initialization
066: */
067: public SimpleHttpServer() throws IOException {
068: this (null, 0);
069: }
070:
071: /**
072: * Creates a new HTTP server instance, using the specified socket
073: * factory and the TCP port
074: *
075: * @param port Desired TCP port
076: * @throws IOException if anything goes wrong during initialization
077: */
078: public SimpleHttpServer(SimpleSocketFactory socketfactory, int port)
079: throws IOException {
080: if (socketfactory == null) {
081: socketfactory = new SimplePlainSocketFactory();
082: }
083: listener = socketfactory.createServerSocket(port);
084: if (LOG.isDebugEnabled()) {
085: LOG.debug("Starting test HTTP server on port "
086: + getLocalPort());
087: }
088: tg = new ThreadGroup("SimpleHttpServer thread group");
089: t = new Thread(tg, this , "SimpleHttpServer listener");
090: t.setDaemon(true);
091: t.start();
092: }
093:
094: /**
095: * Creates a new HTTP server instance, using the specified TCP port
096: *
097: * @param port Desired TCP port
098: * @throws IOException if anything goes wrong during initialization
099: */
100: public SimpleHttpServer(int port) throws IOException {
101: this (null, port);
102: }
103:
104: public String getTestname() {
105: return this .testname;
106: }
107:
108: public void setTestname(final String testname) {
109: this .testname = testname;
110: }
111:
112: /**
113: * Returns the TCP port that this HTTP server instance is bound to.
114: *
115: * @return TCP port, or -1 if not running
116: */
117: public int getLocalPort() {
118: return listener.getLocalPort();
119: }
120:
121: /**
122: * Returns the IP address that this HTTP server instance is bound to.
123: * @return String representation of the IP address or <code>null</code> if not running
124: */
125: public String getLocalAddress() {
126: InetAddress address = listener.getInetAddress();
127: // Ugly work-around for older JDKs
128: byte[] octets = address.getAddress();
129: if ((octets[0] == 0) && (octets[1] == 0) && (octets[2] == 0)
130: && (octets[3] == 0)) {
131: return "localhost";
132: } else {
133: return address.getHostAddress();
134: }
135: }
136:
137: /**
138: * Checks if this HTTP server instance is running.
139: *
140: * @return true/false
141: */
142: public boolean isRunning() {
143: if (t == null) {
144: return false;
145: }
146: return t.isAlive();
147: }
148:
149: /**
150: * Stops this HTTP server instance.
151: */
152: public synchronized void destroy() {
153: if (stopped) {
154: return;
155: }
156:
157: this .stopped = true;
158: if (LOG.isDebugEnabled()) {
159: LOG.debug("Stopping test HTTP server on port "
160: + getLocalPort());
161: }
162: tg.interrupt();
163:
164: if (listener != null) {
165: try {
166: listener.close();
167: } catch (IOException e) {
168:
169: }
170: }
171: this .connections.shutdown();
172: }
173:
174: /**
175: * Returns the currently used HttpRequestHandler by this SimpleHttpServer
176: *
177: * @return The used HttpRequestHandler, or null.
178: */
179: public HttpRequestHandler getRequestHandler() {
180: return requestHandler;
181: }
182:
183: /**
184: * Sets the HttpRequestHandler to be used for this SimpleHttpServer.
185: *
186: * @param rh Request handler to be used, or null to disable.
187: */
188: public void setRequestHandler(HttpRequestHandler rh) {
189: this .requestHandler = rh;
190: }
191:
192: public void setHttpService(HttpService service) {
193: setRequestHandler(new HttpServiceHandler(service));
194: }
195:
196: public void run() {
197: try {
198: while (!this .stopped && !Thread.interrupted()) {
199: Socket socket = listener.accept();
200: try {
201: if (this .requestHandler == null) {
202: socket.close();
203: break;
204: }
205: SimpleHttpServerConnection conn = new SimpleHttpServerConnection(
206: socket);
207: this .connections.addConnection(conn);
208:
209: Thread t = new SimpleConnectionThread(tg,
210: this .testname + " thread " + this .count,
211: conn, this .connections, this .requestHandler);
212: t.setDaemon(true);
213: t.start();
214: } catch (IOException e) {
215: LOG.error("I/O error: " + e.getMessage());
216: }
217: this .count++;
218: Thread.sleep(100);
219: }
220: } catch (InterruptedException accept) {
221: } catch (IOException e) {
222: if (!stopped) {
223: LOG.error("I/O error: " + e.getMessage());
224: }
225: } finally {
226: destroy();
227: }
228: }
229: }
|