// 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.slim; import fitnesse.slim.protocol.SlimDeserializer; import fitnesse.slim.protocol.SlimSerializer; import fitnesse.socketservice.SocketServer; import util.FileUtil; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.List; /** * Handle Slim requests. * * Note this class is re-entrant (do not keep instance state!) */ public class SlimServer implements SocketServer { public static final String MALFORMED_INSTRUCTION = "MALFORMED_INSTRUCTION"; public static final String NO_CLASS = "NO_CLASS"; public static final String NO_INSTANCE = "NO_INSTANCE"; public static final String NO_CONVERTER_FOR_ARGUMENT_NUMBER = "NO_CONVERTER_FOR_ARGUMENT_NUMBER"; public static final String NO_CONSTRUCTOR = "NO_CONSTRUCTOR"; public static final String NO_METHOD_IN_CLASS = "NO_METHOD_IN_CLASS"; public static final String COULD_NOT_INVOKE_CONSTRUCTOR = "COULD_NOT_INVOKE_CONSTRUCTOR"; public static final String TIMED_OUT = "TIMED_OUT"; public static final String EXCEPTION_TAG = "__EXCEPTION__:"; public static final String EXCEPTION_STOP_TEST_TAG = "__EXCEPTION__:ABORT_SLIM_TEST:"; public static final String EXCEPTION_STOP_SUITE_TAG = "__EXCEPTION__:ABORT_SLIM_SUITE:"; private final SlimFactory slimFactory; public SlimServer(SlimFactory slimFactory) { this.slimFactory = slimFactory; } @Override public void serve(Socket s) throws IOException { SlimStreamReader reader = null; OutputStream writer = null; try { reader = SlimStreamReader.getReader(s); writer = SlimStreamReader.getByteWriter(s); tryProcessInstructions(reader, writer); } finally { slimFactory.stop(); FileUtil.close(reader); FileUtil.close(writer); } } private void tryProcessInstructions(SlimStreamReader reader, OutputStream writer) throws IOException { ListExecutor executor = slimFactory.getListExecutor(); String header = SlimVersion.SLIM_HEADER + SlimVersion.VERSION + "\n"; SlimStreamReader.sendSlimHeader(writer, header); boolean more = true; while (more) more = processOneSetOfInstructions(reader, writer, executor); } private boolean processOneSetOfInstructions(SlimStreamReader reader, OutputStream writer, ListExecutor executor) throws IOException { String instructions = reader.getSlimMessage(); // Not sure why this is need but we keep it. if (instructions == null) return true; // We are done Bye Bye message received if (instructions.equalsIgnoreCase(SlimVersion.BYEMESSAGE)) { return false; } // Do some real work String resultString = executeInstructions(executor, instructions); SlimStreamReader.sendSlimMessage(writer, resultString); return true; } private String executeInstructions(ListExecutor executor, String instructions) { List<Object> statements = SlimDeserializer.deserialize(instructions); List<Object> results = executor.execute(statements); return SlimSerializer.serialize(results); } }