// 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; import java.io.IOException; import java.io.OutputStream; import java.net.ServerSocket; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; import fitnesse.http.MockRequestBuilder; import fitnesse.http.MockResponseSender; import fitnesse.http.Request; import fitnesse.http.Response; import fitnesse.socketservice.SocketService; import fitnesse.util.MockSocket; import fitnesse.util.SerialExecutorService; public class FitNesse { private static final Logger LOG = Logger.getLogger(FitNesse.class.getName()); private final FitNesseContext context; private final ExecutorService executorService; private volatile SocketService theService; public FitNesse(FitNesseContext context) { this.context = context; RejectedExecutionHandler rejectionHandler = new RejectedExecutionHandler() { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { LOG.log(Level.WARNING, "Could not handle request. Thread pool is exhausted."); } }; this.executorService = new ThreadPoolExecutor(5, 100, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), new DaemonThreadFactory(), rejectionHandler); } public void start(ServerSocket serverSocket) throws IOException { theService = new SocketService(new FitNesseServer(context, executorService), false, serverSocket); } public synchronized void stop() throws IOException { if (theService != null) { theService.close(); theService = null; } if (!executorService.isShutdown()) { executorService.shutdown(); } } public boolean isRunning() { return theService != null; } public void executeSingleCommand(String command, OutputStream out) throws Exception { Request request = new MockRequestBuilder(command).noChunk().build(); FitNesseExpediter expediter = new FitNesseExpediter(new MockSocket(), context, new SerialExecutorService()); Response response = expediter.createGoodResponse(request); if (response.getStatus() != 200){ throw new Exception("error loading page: " + response.getStatus()); } response.withoutHttpHeaders(); MockResponseSender sender = new MockResponseSender(out); sender.doSending(response); } /** * The default thread factory - creates daemon threads */ static class DaemonThreadFactory implements ThreadFactory { private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; DaemonThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "server-thread-"; } @Override public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); t.setDaemon(true); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } } }