Package fitnesse.testsystems.slim

Source Code of fitnesse.testsystems.slim.SlimCommandRunningClient$ToListExecutor

// 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.testsystems.slim;

import fitnesse.slim.SlimError;
import fitnesse.slim.SlimException;
import fitnesse.slim.instructions.*;
import fitnesse.slim.protocol.SlimDeserializer;
import fitnesse.slim.protocol.SlimSerializer;
import fitnesse.testsystems.CommandRunner;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import util.StreamReader;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import static java.util.Arrays.asList;

public class SlimCommandRunningClient implements SlimClient {
  private static final Logger LOG = Logger.getLogger(SlimCommandRunningClient.class.getName());

  public static final int NO_SLIM_SERVER_CONNECTION_FLAG = -32000;
  public static double MINIMUM_REQUIRED_SLIM_VERSION = 0.3;

  private final CommandRunner slimRunner;
  private final int connectionTimeout;
  private final double requiredSlimVersion;
  private Socket client;
  private StreamReader reader;
  private BufferedWriter writer;
  private String slimServerVersionMessage;
  private double slimServerVersion;
  private String hostName;
  private int port;

  public SlimCommandRunningClient(CommandRunner slimRunner, String hostName, int port, int connectionTimeout, double requiredSlimVersion) {
    this.slimRunner = slimRunner;
    this.hostName = hostName;
    this.port = port;
    this.connectionTimeout = connectionTimeout;
    this.requiredSlimVersion = requiredSlimVersion;
  }

  @Override
  public void start() throws IOException {
    slimRunner.asynchronousStart();
    connect();
    checkForVersionMismatch();
  }

  private void checkForVersionMismatch() {
    double serverVersionNumber = getServerVersion();
    if (serverVersionNumber == NO_SLIM_SERVER_CONNECTION_FLAG) {
      throw new SlimError("Slim Protocol Version Error: Server did not respond with a valid version number.");
    }
    else if (serverVersionNumber < requiredSlimVersion) {
      throw new SlimError(String.format("Slim Protocol Version Error: Expected V%s but was V%s", requiredSlimVersion, serverVersionNumber));
    }
  }

  @Override
  public void kill() throws IOException {
    if (slimRunner != null)
      slimRunner.kill();
    if (reader != null)
      reader.close();
    if (writer != null)
      writer.close();
    if (client != null)
      client.close();
  }

  @Override
  public void connect() throws IOException {
    int maxTries = connectionTimeout * 20; // wait time is 50 ms
    while (client == null) {
      client = tryConnect(maxTries--);
    }
    reader = new StreamReader(client.getInputStream());
    writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8"));
    slimServerVersionMessage = reader.readLine();
    validateConnection();
  }

  private void validateConnection() {
    if (isConnected()) {
      slimServerVersion = Double.parseDouble(slimServerVersionMessage.replace("Slim -- V", ""));
    }
    else {
      slimServerVersion =  NO_SLIM_SERVER_CONNECTION_FLAG;
      LOG.warning("Error reading Slim Version. Read the following: " + slimServerVersionMessage);
    }
  }

  private Socket tryConnect(int maxTries) throws IOException {
    try {
      return new Socket(hostName, port);
    } catch (IOException e) {
      if (maxTries <= 1) {
        throw new SlimError("Error connecting to SLiM server on " + hostName + ":" + port, e);
      } else {
        try {
          Thread.sleep(50);
        } catch (InterruptedException i) {
          throw new SlimError("Wait for connection interrupted.");
        }
        return null;
      }
    }
  }

  public double getServerVersion() {
    return slimServerVersion;
  }

  public boolean isConnected() {
    return slimServerVersionMessage.startsWith("Slim -- V");
  }

  @Override
  public Map<String, Object> invokeAndGetResponse(List<Instruction> statements) throws IOException {
    if (statements.size() == 0)
      return new HashMap<String, Object>();
    String instructions = SlimSerializer.serialize(toList(statements));
    writeString(instructions);
    int resultLength = getLengthToRead();
    String results = reader.read(resultLength);
    // resultList is a list: [tag, resultValue]
    List<Object> resultList = SlimDeserializer.deserialize(results);
    return resultToMap(resultList);
  }

  private interface ToListExecutor extends InstructionExecutor {

  }

  private List<Object> toList(List<Instruction> instructions) {
    final List<Object> statementsAsList = new ArrayList<Object>(instructions.size());
    for (final Instruction instruction: instructions) {
      ToListExecutor executor = new ToListExecutor() {
        @Override
        public void addPath(String path) throws SlimException {
          statementsAsList.add(asList(instruction.getId(), ImportInstruction.INSTRUCTION, path));
        }

        @Override
        public Object callAndAssign(String symbolName, String instanceName, String methodsName, Object... arguments) throws SlimException {
          Object[] list = new Object[] { instruction.getId(), CallAndAssignInstruction.INSTRUCTION, symbolName, instanceName, methodsName };
          statementsAsList.add(asList(ArrayUtils.addAll(list, arguments)));
          return null;
        }

        @Override
        public Object call(String instanceName, String methodName, Object... arguments) throws SlimException {
          Object[] list = new Object[] { instruction.getId(), CallInstruction.INSTRUCTION, instanceName, methodName };
          statementsAsList.add(asList(ArrayUtils.addAll(list, arguments)));
          return null;
        }

        @Override
        public void create(String instanceName, String className, Object... constructorArgs) throws SlimException {
          Object[] list = new Object[] { instruction.getId(), MakeInstruction.INSTRUCTION, instanceName, className };
          statementsAsList.add(asList(ArrayUtils.addAll(list, constructorArgs)));
        }

        @Override
        public void assign(String symbolName, Object value) {
          if (slimServerVersion < 0.4) {
            throw new SlimError("The assign instruction is available as of SLIM protocol version 0.4");
          }
          Object[] list = new Object[] { instruction.getId(), AssignInstruction.INSTRUCTION, symbolName, value };
          statementsAsList.add(asList(list));
        }
      };

      instruction.execute(executor);
    }
    return statementsAsList;
  }

  private int getLengthToRead() throws IOException  {
    String length = reader.read(6);
    try {
      Integer resultLength = Integer.parseInt(length);

      String next;
      while (StringUtils.isNumeric(next = reader.read(1)))
        resultLength = resultLength * 10 + Integer.valueOf(next);

      return resultLength;
    }
    catch (NumberFormatException e){
      throw new IOException("Stream Read Failure. Can't read length of message from the server.  Possibly test aborted.  Last thing read: " + length);
    }
  }

  protected void writeString(String string) throws IOException {
    String packet = String.format("%06d:%s", string.getBytes("UTF-8").length, string);
    writer.write(packet);
    writer.flush();
  }

  @Override
  public void bye() throws IOException {
    writeString("bye");
    slimRunner.join();
    kill();
  }

  public static Map<String, Object> resultToMap(List<?> slimResults) {
    Map<String, Object> map = new HashMap<String, Object>();
    for (Object aResult : slimResults) {
      List<Object> resultList = (List<Object>) aResult;
      map.put((String) resultList.get(0), resultList.get(1));
    }
    return map;
  }
}
TOP

Related Classes of fitnesse.testsystems.slim.SlimCommandRunningClient$ToListExecutor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.