/** * Copyright (c) 2009 - 2011 AppWork UG(haftungsbeschränkt) <e-mail@appwork.org> * * This file is part of org.appwork.utils.net.httpserver * * This software is licensed under the Artistic License 2.0, * see the LICENSE file or http://www.opensource.org/licenses/artistic-license-2.0.php * for details */ package org.appwork.utils.net.httpserver; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; import java.net.UnknownHostException; import java.util.LinkedList; /** * @author daniel * */ public class HttpServer implements Runnable { private final int port; private ServerSocket controlSocket; private Thread controlThread = null; private ThreadGroup threadGroup = null; private boolean localhostOnly = false; private boolean debug = false; private LinkedList<HttpRequestHandler> handler = null; public HttpServer(final int port) { this.port = port; this.threadGroup = new ThreadGroup("HttpServer"); this.handler = new LinkedList<HttpRequestHandler>(); } public LinkedList<HttpRequestHandler> getHandler() { return this.handler; } protected InetAddress getLocalHost() { InetAddress localhost = null; try { localhost = InetAddress.getByName("127.0.0.1"); } catch (final UnknownHostException e1) { } if (localhost != null) { return localhost; } try { localhost = InetAddress.getByName(null); } catch (final UnknownHostException e1) { } return localhost; } /** * @return the clientThreadGroup */ protected ThreadGroup getThreadGroup() { return this.threadGroup; } /** * @return the debug */ public boolean isDebug() { return this.debug; } /** * @return the localhostOnly */ public boolean isLocalhostOnly() { return this.localhostOnly; } /* * to register a new handler we create a copy of current handlerList and * then add new handler to it and set it as new handlerList. by doing so, * all current connections dont have to sync on their handlerlist */ public void registerRequestHandler(final HttpRequestHandler handler) { synchronized (this.handler) { @SuppressWarnings("unchecked") final LinkedList<HttpRequestHandler> newhandler = (LinkedList<HttpRequestHandler>) this.handler.clone(); newhandler.add(handler); this.handler = newhandler; } } public void run() { final Thread current = this.controlThread; final ServerSocket socket = this.controlSocket; try { while (true) { try { final Socket clientSocket = socket.accept(); new HttpConnection(this, clientSocket); } catch (final IOException e) { break; } if (current == null || current.isInterrupted()) { break; } } } finally { try { socket.close(); } catch (final Throwable e) { } } } /** * @param debug * the debug to set */ public void setDebug(final boolean debug) { this.debug = debug; } /** * @param localhostOnly * the localhostOnly to set */ public void setLocalhostOnly(final boolean localhostOnly) { this.localhostOnly = localhostOnly; } /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ public synchronized void start() throws IOException { if (this.isLocalhostOnly()) { /* we only want localhost bound here */ final SocketAddress socketAddress = new InetSocketAddress(this.getLocalHost(), this.port); this.controlSocket = new ServerSocket(); this.controlSocket.bind(socketAddress); } else { this.controlSocket = new ServerSocket(this.port); } this.controlThread = new Thread(this.threadGroup, this); this.controlThread.setName("HttpServerThread"); this.controlThread.start(); } public synchronized void stop() { try { this.controlSocket.close(); } catch (final Throwable e) { } this.threadGroup.interrupt(); } /* * to unregister a new handler we create a copy of current handlerList and * then remove handler to it and set it as new handlerList. by doing so, all * current connections dont have to sync on their handlerlist */ public void unregisterRequestHandler(final HttpRequestHandler handler) { synchronized (this.handler) { @SuppressWarnings("unchecked") final LinkedList<HttpRequestHandler> newhandler = (LinkedList<HttpRequestHandler>) this.handler.clone(); newhandler.remove(handler); this.handler = newhandler; } } }