/* * $Header: /home/data/cvs/rt/org.eclipse.ecf/tests/bundles/org.eclipse.ecf.tests.apache.httpclient.server/src/org/apache/commons/httpclient/server/SimpleHttpServer.java,v 1.2 2009/02/17 21:58:54 slewis Exp $ * $Revision: 1.2 $ * $Date: 2009/02/17 21:58:54 $ * * ==================================================================== * * Copyright 1999-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.commons.httpclient.server; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * A simple, but extensible HTTP server, mostly for testing purposes. * * @author Christian Kohlschuetter * @author Oleg Kalnichevski */ public class SimpleHttpServer implements Runnable { private static final Log LOG = LogFactory.getLog(SimpleHttpServer.class); private String testname = "Simple test"; private long count = 0; private ServerSocket listener = null; private Thread t; private ThreadGroup tg; private boolean stopped = false; private SimpleConnSet connections = new SimpleConnSet(); private HttpRequestHandler requestHandler = null; /** * Creates a new HTTP server instance, using an arbitrary free TCP port * * @throws IOException if anything goes wrong during initialization */ public SimpleHttpServer() throws IOException { this(""); } public SimpleHttpServer(String serverThreadName) throws IOException { this(serverThreadName, null, 0); } /** * Creates a new HTTP server instance, using the specified socket * factory and the TCP port * * @param port Desired TCP port * @throws IOException * @throws IOException if anything goes wrong during initialization */ public SimpleHttpServer(SimpleSocketFactory socketfactory, int port) throws IOException { this("", socketfactory, port); } public SimpleHttpServer(String serverThreadName, SimpleSocketFactory socketfactory, int port) throws IOException { if (socketfactory == null) { socketfactory = new SimplePlainSocketFactory(); } listener = socketfactory.createServerSocket(port); if(LOG.isDebugEnabled()) { LOG.debug("Starting test HTTP server on port " + getLocalPort()); } tg = new ThreadGroup("SimpleHttpServer thread group"); t = new Thread(tg, this, serverThreadName + "(SimpleHttpServer listener at port " + listener.getLocalPort() + ")"); t.setDaemon(true); t.start(); } /** * Creates a new HTTP server instance, using the specified TCP port * * @param port Desired TCP port * @throws IOException if anything goes wrong during initialization */ public SimpleHttpServer(int port) throws IOException { this("", null, port); } public SimpleHttpServer(String serverThreadName, int port) throws IOException { this(serverThreadName, null, port); } public String getTestname() { return this.testname; } public void setTestname(final String testname) { this.testname = testname; } /** * Returns the TCP port that this HTTP server instance is bound to. * * @return TCP port, or -1 if not running */ public int getLocalPort() { return listener.getLocalPort(); } /** * Returns the IP address that this HTTP server instance is bound to. * @return String representation of the IP address or <code>null</code> if not running */ public String getLocalAddress() { InetAddress address = listener.getInetAddress(); // Ugly work-around for older JDKs byte[] octets = address.getAddress(); if ((octets[0] == 0) && (octets[1] == 0) && (octets[2] == 0) && (octets[3] == 0)) { return "localhost"; } else { return address.getHostAddress(); } } /** * Checks if this HTTP server instance is running. * * @return true/false */ public boolean isRunning() { if(t == null) { return false; } return t.isAlive(); } /** * Stops this HTTP server instance. */ public synchronized void destroy() { if (stopped) { return; } this.stopped = true; if(LOG.isDebugEnabled()) { LOG.debug("Stopping test HTTP server on port " + getLocalPort()); } tg.interrupt(); if (listener != null) { try { listener.close(); } catch(IOException e) { } } this.connections.shutdown(); } /** * Returns the currently used HttpRequestHandler by this SimpleHttpServer * * @return The used HttpRequestHandler, or null. */ public HttpRequestHandler getRequestHandler() { return requestHandler; } /** * Sets the HttpRequestHandler to be used for this SimpleHttpServer. * * @param rh Request handler to be used, or null to disable. */ public void setRequestHandler(HttpRequestHandler rh) { this.requestHandler = rh; } public void setHttpService(HttpService service) { setRequestHandler(new HttpServiceHandler(service)); } public void run() { try { while (!this.stopped && !Thread.interrupted()) { Socket socket = listener.accept(); try { if (this.requestHandler == null) { socket.close(); break; } SimpleHttpServerConnection conn = new SimpleHttpServerConnection(socket); this.connections.addConnection(conn); Thread t = new SimpleConnectionThread( tg, this.testname + " thread " + this.count, conn, this.connections, this.requestHandler); t.setDaemon(true); t.start(); } catch (IOException e) { LOG.error("I/O error: " + e.getMessage()); } this.count++; Thread.sleep(100); } } catch (InterruptedException accept) { } catch (IOException e) { if (!stopped) { LOG.error("I/O error: " + e.getMessage()); } } finally { destroy(); } } }