// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved. // Released under the terms of the CPL Common Public License version 1.0. package fitnesse.socketservice; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.logging.Level; import java.util.logging.Logger; /** * Runs a separate service (thread) to handle new connections. */ public class SocketService { private static final Logger LOG = Logger.getLogger(SocketService.class.getName()); private final ServerSocket serverSocket; private final Thread serviceThread; private volatile boolean running = false; private final SocketServer server; private volatile boolean everRan = false; public SocketService(SocketServer server, boolean daemon, ServerSocket serverSocket) throws IOException { this.server = server; this.serverSocket = serverSocket; serviceThread = new Thread( new Runnable() { @Override public void run() { serviceThread(); } } ); serviceThread.setDaemon(daemon); serviceThread.start(); } public void close() throws IOException { waitForServiceThreadToStart(); running = false; serverSocket.close(); try { serviceThread.join(); } catch (InterruptedException e) { LOG.log(Level.WARNING, "Thread joining interrupted"); Thread.currentThread().interrupt(); } } private void waitForServiceThreadToStart() { if (everRan) return; while (!running) Thread.yield(); } private void serviceThread() { running = true; while (running) { try { Socket s = serverSocket.accept(); everRan = true; server.serve(s); } catch (java.lang.OutOfMemoryError e) { LOG.log(Level.SEVERE, "Can't create new thread. Out of Memory. Aborting.", e); System.exit(99); } catch (SocketException sox) { running = false; } catch (IOException e) { LOG.log(Level.SEVERE, "I/O exception in service thread", e); } } } }