// Modified or written by Object Mentor, Inc. for inclusion with FitNesse. // Copyright (c) 2002 Cunningham & Cunningham, Inc. // Released under the terms of the GNU General Public License version 2 or later. package fit; import java.io.*; import java.net.Socket; import util.CommandLine; import util.StreamReader; import util.FileUtil; import fit.exception.FitParseException; public class FitServer { public String input; public Fixture fixture = new Fixture(); public FixtureListener fixtureListener = new TablePrintingFixtureListener(); private Counts counts = new Counts(); private OutputStream socketOutput; private StreamReader socketReader; private boolean verbose = false; private String host; private int port; private int socketToken; private Socket socket; private boolean noExit; private boolean sentinel; public FitServer(String host, int port, boolean verbose) { this.host = host; this.port = port; this.verbose = verbose; } public FitServer() { } public static void main(String[] argv) throws Exception { FitServer fitServer = new FitServer(); fitServer.run(argv); if (!fitServer.noExit) System.exit(fitServer.exitCode()); } public void run(String[] argv) throws Exception { args(argv); File sentinelFile = null; if (sentinel) { String sentinelName = sentinelName(port); sentinelFile = new File(sentinelName); sentinelFile.createNewFile(); } establishConnection(); validateConnection(); process(); closeConnection(); if (sentinel) FileUtil.deleteFile(sentinelFile); exit(); } public static String sentinelName(int thePort) { return String.format("fitserverSentinel%d", thePort); } public void closeConnection() throws IOException { socket.close(); } public void process() { fixture.listener = fixtureListener; try { int size = 1; while ((size = FitProtocol.readSize(socketReader)) != 0) { try { print("processing document of size: " + size + "\n"); String document = FitProtocol.readDocument(socketReader, size); //TODO MDM if the page name was always the first line of the body, it could be printed here. Parse tables = new Parse(document); newFixture().doTables(tables); print("\tresults: " + fixture.counts() + "\n"); counts.tally(fixture.counts); } catch (FitParseException e) { exception(e); } } print("completion signal recieved" + "\n"); } catch (Exception e) { exception(e); } } public String readDocument() throws Exception { int size = FitProtocol.readSize(socketReader); return FitProtocol.readDocument(socketReader, size); } protected Fixture newFixture() { fixture = new Fixture(); fixture.listener = fixtureListener; return fixture; } public void args(String[] argv) { CommandLine commandLine = new CommandLine("[-v][-x][-s] host port socketToken"); if (commandLine.parse(argv)) { host = commandLine.getArgument("host"); port = Integer.parseInt(commandLine.getArgument("port")); socketToken = Integer.parseInt(commandLine.getArgument("socketToken")); verbose = commandLine.hasOption("v"); noExit = commandLine.hasOption("x"); sentinel = commandLine.hasOption("s"); } else usage(); } private void usage() { System.out.println("usage: java fit.FitServer [-v] host port socketTicket"); System.out.println("\t-v\tverbose"); System.exit(-1); } protected void exception(Exception e) { print("Exception occurred!" + "\n"); print("\t" + e.getMessage() + "\n"); Parse tables = new Parse("span", "Exception occurred: ", null, null); fixture.exception(tables, e); counts.exceptions += 1; fixture.listener.tableFinished(tables); fixture.listener.tablesFinished(counts); //TODO shouldn't this be fixture.counts } public void exit() throws Exception { print("exiting" + "\n"); print("\tend results: " + counts.toString() + "\n"); } public int exitCode() { return counts.wrong + counts.exceptions; } public void establishConnection() throws Exception { establishConnection(makeHttpRequest()); } public void establishConnection(String httpRequest) throws Exception { socket = new Socket(host, port); socketOutput = socket.getOutputStream(); socketReader = new StreamReader(socket.getInputStream()); byte[] bytes = httpRequest.getBytes(FileUtil.CHARENCODING); socketOutput.write(bytes); socketOutput.flush(); print("http request sent" + "\n"); } private String makeHttpRequest() { return "GET /?responder=socketCatcher&ticket=" + socketToken + " HTTP/1.1\r\n\r\n"; } public void validateConnection() throws Exception { print("validating connection..."); int statusSize = FitProtocol.readSize(socketReader); if (statusSize == 0) print("...ok" + "\n"); else { String errorMessage = FitProtocol.readDocument(socketReader, statusSize); print("...failed because: " + errorMessage + "\n"); System.out.println("An error occurred while connecting to client."); System.out.println(errorMessage); System.exit(-1); } } public Counts getCounts() { return counts; } private void print(String message) { if (verbose) System.out.print(message); } public static byte[] readTable(Parse table) throws Exception { ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); OutputStreamWriter streamWriter = new OutputStreamWriter(byteBuffer, FileUtil.CHARENCODING); PrintWriter writer = new PrintWriter(streamWriter); Parse more = table.more; table.more = null; if (table.trailer == null) table.trailer = ""; table.print(writer); table.more = more; writer.close(); return byteBuffer.toByteArray(); } public void writeCounts(Counts count) throws IOException { //TODO This can't be right.... which counts should be used? FitProtocol.writeCounts(counts, socketOutput); } class TablePrintingFixtureListener implements FixtureListener { @Override public void tableFinished(Parse table) { try { byte[] bytes = readTable(table); if (bytes.length > 0) FitProtocol.writeData(bytes, socketOutput); } catch (Exception e) { e.printStackTrace(); } } @Override public void tablesFinished(Counts count) { try { FitProtocol.writeCounts(count, socketOutput); } catch (IOException e) { e.printStackTrace(); } } } }