org.testeditor.fixture.swt.SwtBotFixture.java Source code

Java tutorial

Introduction

Here is the source code for org.testeditor.fixture.swt.SwtBotFixture.java

Source

/*******************************************************************************
 * Copyright (c) 2012 - 2015 Signal Iduna Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Signal Iduna Corporation - initial API and implementation
 * akquinet AG
 *******************************************************************************/
package org.testeditor.fixture.swt;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ConnectException;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;
import org.testeditor.fixture.core.elementlist.ElementListService;
import org.testeditor.fixture.core.exceptions.ElementKeyNotFoundException;
import org.testeditor.fixture.core.exceptions.StopTestException;
import org.testeditor.fixture.core.interaction.Fixture;
import org.testeditor.fixture.core.interaction.StoppableFixture;
import org.testeditor.util.PerformanceLogHandler;

import com.jamonapi.Monitor;
import com.jamonapi.MonitorFactory;

/**
 * Fixture for communication via socket with swtbot agent.
 * 
 */
public class SwtBotFixture implements StoppableFixture, Fixture {
    private static final Logger LOGGER = Logger.getLogger(SwtBotFixture.class);
    private static final int AGENT_PORT = 9090;
    private static final String AGENT_HOST = "localhost";
    private static final String COMMAND_DELIMITER = ";";
    // Agent commands
    private static final String STOP_APPLICATION = "stop";
    private static final String CHARSET_UTF_8 = "UTF-8";

    private ElementListService elementListService;
    private Process process;
    private static boolean runningApp = false;
    private String testName;
    private Monitor javaMon;
    private List<String> launchApplicationCommandList;

    /**
     * Creates the element list instance representing the GUI-Map for widget
     * element id's of an application and the user defined names for this
     * represented GUI element. Often used in a FitNesse ScenarioLibrary for
     * configuration purpose. <br />
     * 
     * Usage for FitNesse: |set elementlist|../ElementList/content.txt|
     * 
     * @param elementList
     *            relative path of the element list content.txt wiki site on a
     *            FitNesse Server where WikiPages is the directory where all the
     *            Wiki Sites of the recent project are
     */
    public void setElementlist(String elementList) {
        this.elementListService = ElementListService.instanceFor(elementList);
    }

    /**
     * Stops running AUT.
     * 
     */
    public void stopApplication() {
        try {
            Socket client = getSocket();
            PrintStream os = new PrintStream(client.getOutputStream(), false, CHARSET_UTF_8);
            os.println(STOP_APPLICATION);
            client.close();
            boolean appTerminated = false;
            while (!appTerminated) {
                try {
                    process.exitValue();
                    appTerminated = true;
                    LOGGER.info("AUT terminated.");
                } catch (IllegalThreadStateException e) {
                    LOGGER.info("AUT is shutting down...");
                }
                Thread.sleep(100);
            }

            writePerformanceLog();

            Runtime.getRuntime().addShutdownHook(addConfigCleaner());
        } catch (UnknownHostException e) {
            LOGGER.error("stopApplication UnknownHostException: ", e);
        } catch (IOException e) {
            LOGGER.error("stopApplication IOException ", e);
        } catch (InterruptedException e) {
            LOGGER.error("stopApplication ", e);
        } finally {
            if (process != null) {
                process.destroy();
            }
            markApplicationStopped();
        }
    }

    /**
     * cleans the configuration of application_under_test.
     * 
     * @return the new thread
     */
    private Thread addConfigCleaner() {
        return new Thread() {
            @Override
            public void run() {
                try {
                    FileVisitor<Path> visitor = getDeleteFileVisitor();
                    Path configPath = new File(
                            System.getProperty("java.io.tmpdir") + File.separator + "configuration").toPath();
                    Files.walkFileTree(configPath, visitor);
                    LOGGER.info("Cleaning up temporary configuration of the RCP AUT.");
                } catch (IOException e) {
                    LOGGER.error("Error deleting temporary RCP config.", e);
                }

            }
        };
    }

    /**
     * 
     * @return utility FileVisitor class for recursive directory delete
     *         operations.
     */
    private FileVisitor<Path> getDeleteFileVisitor() {
        return new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                file.toFile().setWritable(true);
                Files.delete(file);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                Files.delete(dir);
                return FileVisitResult.CONTINUE;
            }
        };
    }

    /**
     * Expands nodes in tree. Can expand all nodes, their given a list of nodes.
     * 
     * e.g. expandTreeItems;node1,node2,nodeN...
     * 
     * @param nodeList
     *            node1,node2,nodeN..
     * @return the result of the message.
     */
    public boolean expandTreeItems(String nodeList) {
        return sendMessage("expandTreeItems" + COMMAND_DELIMITER + nodeList);
    }

    /**
     * Selects an Element ore more in a Table.
     * 
     * @param index
     *            to be selected.
     * @return the result of the message.
     */
    public boolean selectTableAtIndex(String index) {
        return sendMessage("selectTableAtIndex" + COMMAND_DELIMITER + index);
    }

    /**
     * clicks a menuitem of a contextmenu.
     * 
     * @param menuItemName
     *            name of menuitem
     * @return the result of the message.
     */
    public boolean clickContextMenu(String menuItemName) {
        return sendMessage("clickContextMenu" + COMMAND_DELIMITER + getLocator(menuItemName));
    }

    /**
     * 
     * @param locator
     *            locator-id or key of the text.
     * @param inputText
     *            string
     * @return the result of the message.
     */
    public boolean setTextById(String locator, String inputText) {
        return sendMessage("setTextById" + COMMAND_DELIMITER + getLocator(locator) + COMMAND_DELIMITER + inputText);
    }

    /**
     * 
     * @param menuName
     *            name of the menu
     * @return the result of the message.
     */
    public boolean clickMenuByName(String menuName) {
        return sendMessage("clickMenuByName" + COMMAND_DELIMITER + getLocator(menuName));
    }

    /**
     * 
     * @param id
     *            of the menu-item
     * @return the result of the message.
     */
    public boolean clickMenuById(String id) {
        LOGGER.error("clickMenuById: " + getLocator(id));
        return sendMessage("clickMenuById" + COMMAND_DELIMITER + getLocator(id));

    }

    /**
     * 
     * @param locator
     *            locator-id or key of the button
     * @return the result of the message.
     */
    public boolean clickButton(String locator) {
        return sendMessage("clickButton" + COMMAND_DELIMITER + getLocator(locator));
    }

    /**
     * Starts the Application again. The workspace is not dropped and recreated.
     * It used also the previous launch configuration of the
     * 
     * @return true if the new start of the application works.
     */
    public boolean startApplicationAgain() {
        try {
            LOGGER.info("Start the application again. The last workspace is used.");
            waitUntilPreviousLaunchIsFinished();
            createAndLaunchProcess();
        } catch (Exception e) {
            LOGGER.error("Error Test execution: ", e);
            throw new StopTestException(e);
        }
        return true;
    }

    /**
     * 
     * @param locator
     *            locator-id or key of the check box or the check box label
     * @return the result of the message.
     */
    public boolean clickCheckBox(String locator) {
        return sendMessage("clickCheckBox" + COMMAND_DELIMITER + getLocator(locator));
    }

    /**
     * 
     * @param locator
     *            locator-id or key of the check box
     * @return the result of the message.
     */
    public boolean isCheckBoxEnabled(String locator) {
        return sendMessage("isCheckBoxEnabled" + COMMAND_DELIMITER + getLocator(locator));
    }

    /**
     * 
     * @param locator
     *            locator-id or key of the check box
     * @return the result of the message.
     */
    public boolean isCheckBoxDisabled(String locator) {
        return !sendMessage("isCheckBoxEnabled" + COMMAND_DELIMITER + getLocator(locator));
    }

    /**
     * 
     * @param locator
     *            locator-id or key of the check box
     * @return the result of the message.
     */
    public boolean isCheckBoxChecked(String locator) {
        return sendMessage("isCheckBoxChecked" + COMMAND_DELIMITER + getLocator(locator));
    }

    /**
     * 
     * @param locator
     *            locator-id or key of the check box
     * @return the result of the message.
     */
    public boolean isCheckBoxNotChecked(String locator) {
        return !sendMessage("isCheckBoxChecked" + COMMAND_DELIMITER + getLocator(locator));
    }

    /**
     * 
     * @param locator
     *            locator-id or key of the button
     * @return the result of the message.
     */
    public boolean isButtonEnabled(String locator) {
        LOGGER.error("isButtonEnabled: " + locator);
        return sendMessage("isButtonEnabled" + COMMAND_DELIMITER + getLocator(locator));
    }

    /**
     * reads all projects in the tree and trace the names of them to the
     * SWT.log.
     * 
     * @return the result of the message.
     */
    public boolean readAllProjectsInTree() {
        return sendMessage("readAllProjectsInTree");
    }

    /**
     * deletes all projects.
     * 
     * @return the result of the message.
     */
    public boolean deleteAllProjects() {
        return sendMessage("deleteAllProjects");
    }

    /**
     * compares the count of the projects with the parameter expectedCount.
     * 
     * @param expectedCount
     *            the expected number of projects
     * @return the result of the message.
     */
    public boolean countProjectsEquals(String expectedCount) {
        return sendMessage("countProjectsEquals" + COMMAND_DELIMITER + expectedCount);
    }

    /**
     * compares the number of children of the parent with the expectedCount.
     * 
     * @param parentName
     *            as nodes from the root separated by comma
     * @param expectedCount
     *            the expected count of children
     * @return the result of the message.
     */
    public boolean countChildrenEquals(String parentName, String expectedCount) {
        return sendMessage(
                "countChildrenEquals" + COMMAND_DELIMITER + parentName + COMMAND_DELIMITER + expectedCount);
    }

    /**
     * Compare the count of a list with expected count.
     * 
     * @param locator
     *            locator id of the widget with items.
     * @param expectedCount
     *            count of items in the widget.
     * @return true if the amount of items equals the expectedCount.
     */
    public boolean countItemsEquals(String locator, String expectedCount) {
        return sendMessage(
                "countItemsEquals" + COMMAND_DELIMITER + getLocator(locator) + COMMAND_DELIMITER + expectedCount);
    }

    /**
     * 
     * @param locator
     *            locator-id or key of the button
     * @return the result of the message.
     */
    public boolean isButtonDisabled(String locator) {
        LOGGER.error("isButtonDisabled: " + locator);
        return !sendMessage("isButtonEnabled" + COMMAND_DELIMITER + getLocator(locator));
    }

    /**
     * 
     * @param locator
     *            used to identify the table.
     * @param expectedRowNumber
     *            number of row.
     */
    public boolean checkRowNumberOfTable(String locator, String expectedRowNumber) {
        return sendMessage("checkRowNumberOfTable" + COMMAND_DELIMITER + getLocator(locator) + COMMAND_DELIMITER
                + expectedRowNumber);

    }

    /**
     * <pre>
     * This method checks in a given table and column the searched string in every row.
     * 
     * Example: searched string = login and column in which to be searched = Name
     * 
     *  Result Table
     * 
     *  |        Name          |        Path          |
     *  |______________________|______________________|
     *  |      abcd.login.ab   |  Demo.abcd.login.ab  |
     *  |______________________|______________________|
     *  |      efg.login.fg    |  Demo.efg.login.fg   |
     *  |______________________|______________________|
     *  |      loginAbc        |  Demo.login          |
     *  |______________________|______________________|
     *  |      klm.login       |  Demo.klm.login      |
     * 
     * 
     * </pre>
     * 
     * the result of this method is true when in all rows in given column the
     * searched string is found
     * 
     * 
     * 
     * @param locator
     *            unique id of table
     * @param column
     *            of table
     * @param value
     *            searched value in each row
     * @return true if all entries in table in given column contains given value
     */
    public boolean checkTableIfInColumnContainsInAllRows(String locator, String column, String value) {
        return sendMessage("checkTableIfInColumnContainsInAllRows" + COMMAND_DELIMITER + getLocator(locator)
                + COMMAND_DELIMITER + column + COMMAND_DELIMITER + value);
    }

    /**
     * <pre>
     * This method checks in a given table and column,row the searched string is found.
     * 
     * Example: searched string = login and column in which to be searched = Name
     * 
     *  Result Table
     * 
     *  |        Name          |        Path          |
     *  |______________________|______________________|
     *  |      abcd.login.ab   |  Demo.abcd.login.ab  |
     *  |______________________|______________________|
     *  |      efg.login.fg    |  Demo.efg.login.fg   |
     *  |______________________|______________________|
     *  |      loginAbc        |  Demo.loginAbc       |
     *  |______________________|______________________|
     *  |      klm.login       |  Demo.klm.login      |
     * 
     * 
     * </pre>
     * 
     * the result of this method is true when in all rows in given column the
     * searched string is found
     * 
     * 
     * 
     * @param locator
     *            unique id of table
     * @param column
     *            of table
     * 
     * @param row
     *            searched value in special row
     * @param value
     *            searched value
     * @return true if all entries in table in given column contains given value
     */
    public boolean checkTableIfInColumnAndRowContains(String locator, String column, String row, String value) {
        return sendMessage("checkTableIfInColumnAndRowContains" + COMMAND_DELIMITER + getLocator(locator)
                + COMMAND_DELIMITER + column + COMMAND_DELIMITER + row + COMMAND_DELIMITER + value);
    }

    /**
     * sets playbacktime of SWTBot.
     * 
     * @param milliSeconds
     *            time to wait in milliseconds
     * @return the result of the message.
     */
    public boolean setPlayBackTime(String milliSeconds) {
        // TODO return sendMessage("setStyledTextWithId" + COMMAND_DELIMITER +
        // milliSeconds);
        return false;
    }

    /**
     * Waits for the given period of time before executing the next command. <br />
     * 
     * @param timeToWait
     *            Time to wait in seconds
     * @return always true to show inside FitNesse a positive result
     */
    public boolean waitSeconds(String timeToWait) {
        waitTime(new Long(timeToWait) * 1000);
        return true;
    }

    /**
     * Waits for the given period.
     * 
     * @param milliseconds
     *            Time to wait in milliseconds
     */
    private void waitTime(long milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            LOGGER.error(e.getMessage());
        }
    }

    /**
     * 
     * @param regEx
     *            the regularexpression to identify the button
     * @return the result of the message.
     * 
     */
    public boolean clickButtonByRegEx(String regEx) {
        return sendMessage("clickButtonByRegEx" + COMMAND_DELIMITER + regEx);
    }

    /**
     * Checks if text is visible in any kind of widget (with function
     * getText()).
     * 
     * @param text
     *            Text to be found
     * @return the result of the message
     */
    public boolean checkTextForAllWidgets(String text) {
        LOGGER.error("checkTextForAllWidgets: " + text);
        return sendMessage("checkTextForAllWidgets" + COMMAND_DELIMITER + text);
    }

    /**
     * compares the text in the text-field identified with the id to the
     * comptext.
     * 
     * @param locator
     *            identifier of text
     * @param comptext
     *            text to compare with the content in the text-field.
     * @return the result of the message.
     */
    public boolean compareTextById(String locator, String comptext) {
        return sendMessage(
                "compareTextById" + COMMAND_DELIMITER + getLocator(locator) + COMMAND_DELIMITER + comptext);
    }

    /**
     * compares the text in the label identified with the id to the comptext.
     * 
     * @param locator
     *            identifier of text
     * @param comptext
     *            text to compare with the content in the text-field.
     * @return the result of the message.
     */
    public boolean compareLabelById(String locator, String comptext) {
        return sendMessage(
                "compareLabelById" + COMMAND_DELIMITER + getLocator(locator) + COMMAND_DELIMITER + comptext);
    }

    /**
     * compares the text in the label identified with the id to the comptext and
     * returns true if the text is not in the label.
     * 
     * @param locator
     *            identifier of text
     * @param comptext
     *            text to compare with the content in the text-field.
     * @return the result of the message.
     */
    public boolean compareLabelByIdTextNotInWidget(String locator, String comptext) {
        return !sendMessage(
                "compareLabelById" + COMMAND_DELIMITER + getLocator(locator) + COMMAND_DELIMITER + comptext);
    }

    /**
     * sends the modificationKeys and the key.
     * 
     * @param locator
     *            identifier of styled-text
     * @param modificationKeys
     *            the combination of SWT.ALT | SWT.CTRL | SWT.SHIFT |
     *            SWT.COMMAND.
     * @param key
     *            the character
     * @return true, after sending the keys
     */
    public boolean pressShortcutWithModificationKeyOfStyledText(String locator, String modificationKeys,
            String key) {
        return sendMessage("pressShortcutWithModificationKeyOfStyledText" + COMMAND_DELIMITER + getLocator(locator)
                + COMMAND_DELIMITER + getLocator(modificationKeys) + COMMAND_DELIMITER + key);
    }

    /**
     * Presses the shortcut specified by the given keys.
     * 
     * @param locator
     *            identifier of the StyledText
     * @param key
     *            the key to press as the string-representing of the
     *            Keystrokes
     * @return true, after sending the key
     */
    public boolean pressShortcutOfStyledText(final String locator, final String key) {
        LOGGER.error("pressShortcutOfStyledText" + COMMAND_DELIMITER + getLocator(locator) + COMMAND_DELIMITER
                + getLocator(key));
        return sendMessage("pressShortcutOfStyledText" + COMMAND_DELIMITER + getLocator(locator) + COMMAND_DELIMITER
                + getLocator(key));
    }

    /**
     * sends the modificationKeys and the key to the active window.
     * 
     * @param modificationKeys
     *            the combination of SWT.ALT | SWT.CTRL | SWT.SHIFT |
     *            SWT.COMMAND.
     * @param key
     *            the character
     * @return true, after sending the keys
     */
    public boolean pressGlobalShortcut(String modificationKeys, String key) {
        return sendMessage(
                "pressGlobalShortcut" + COMMAND_DELIMITER + getLocator(modificationKeys) + COMMAND_DELIMITER + key);
    }

    /**
     * 
     * @param locator
     *            locator-id or key of the styled-text.
     * @param lineNumber
     *            linenumber in the text
     * @return the result of the message.
     */
    public boolean selectLineInText(String locator, String lineNumber) {
        return sendMessage(
                "selectLineInText" + COMMAND_DELIMITER + getLocator(locator) + COMMAND_DELIMITER + lineNumber);
    }

    /**
     * 
     * @param locator
     *            locator-id or key of the styled-text.
     * @param contents
     *            part of the line in styled-text to be marked
     * @param position
     *            start-position for the marked range
     * @return the result of the message.
     */
    public boolean setCursorInTextWithContentsAtPosition(String locator, String contents, String position) {
        return sendMessage("setCursorInTextWithContentsAtPosition" + COMMAND_DELIMITER + getLocator(locator)
                + COMMAND_DELIMITER + contents + COMMAND_DELIMITER + position);
    }

    /**
     * 
     * @param locator
     *            locator-id or key of the combobox.
     * @param selectItemAsText
     *            as string.
     * @return the result of the message.
     */
    public boolean selectComboBoxWithId(String locator, String selectItemAsText) {
        return sendMessage("selectComboBoxWithId" + COMMAND_DELIMITER + getLocator(locator) + COMMAND_DELIMITER
                + selectItemAsText);
    }

    /**
     * sends the message clickToolbarButtonWithId.
     * 
     * @param locator
     *            locator-id or key of the button
     * @return the result of the message.
     */
    public boolean clickToolbarButtonWithId(String locator) {
        return sendMessage("clickToolbarButtonWithId" + COMMAND_DELIMITER + getLocator(locator));
    }

    /**
     * 
     * sends the message clickToolbarButtonWithTooltip.
     * 
     * @param locator
     *            locator or key of the button
     * @return the result of the message.
     */
    public boolean clickToolbarButtonWithTooltip(String locator) {
        return sendMessage("clickToolbarButtonWithTooltip" + COMMAND_DELIMITER + getLocator(locator));
    }

    /**
     * sends the message closeTabItemWithName.
     * 
     * @param name
     *            name of the tab
     * @return the result of the message.
     */
    public boolean closeTabItemWithName(String name) {
        return sendMessage("closeTabItemWithName" + COMMAND_DELIMITER + getLocator(name));
    }

    /**
     * sends the message analyzeWidgets.
     * 
     * @return the result of the message.
     */
    public boolean analyzeWidgets() {
        return sendMessage("analyzeWidgets");
    }

    /**
     * checks the visibility of a text given by the parameter.
     * 
     * @param text
     *            the text to check
     * @return true, if the text is visible, else false
     */
    public boolean textIsVisible(String text) {
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("textIsVisible: " + text);
        }
        return sendMessage("textIsVisible" + COMMAND_DELIMITER + text);
    }

    /**
     * checks the visibility of a text given by the parameter.
     * 
     * @param text
     *            the text to check
     * @return true, if the text is invisible, else false
     */
    public boolean textIsInVisible(String text) {
        return !sendMessage("textIsVisible" + COMMAND_DELIMITER + text);
    }

    /**
     * compares in a parameter given comptext with the text in styledText given
     * by id.
     * 
     * @param id
     *            String
     * @param compText
     *            String
     * @return true, if the comptext is in the styledText.
     */
    public boolean compareTextInStyledById(String id, String compText) {
        LOGGER.info("compareTextInStyledById " + id + " " + compText);
        return sendMessage(
                "compareTextInStyledById" + COMMAND_DELIMITER + getLocator(id) + COMMAND_DELIMITER + compText);
    }

    /**
     * compares in a parameter given comptext with the text in styledText given.
     * by id.
     * 
     * @param id
     *            String
     * @param compText
     *            String
     * @return true, if the comptext is not in the styledText.
     */
    public boolean compareTextNotInStyledById(String id, String compText) {
        LOGGER.info("compareTextInStyledById " + id + " " + compText);
        return !sendMessage(
                "compareTextInStyledById" + COMMAND_DELIMITER + getLocator(id) + COMMAND_DELIMITER + compText);
    }

    /**
     * checks that a text not exists in styled-text identified by the locator.
     * 
     * @param locator
     *            locator or key of the styled-text
     * @param text
     *            the searched text
     * @return true, if the text is found, else false
     */
    public boolean checkTextNotExistInWidgets(String locator, String text) {
        return !sendMessage(
                "checkTextExistInWidgets" + COMMAND_DELIMITER + getLocator(locator) + COMMAND_DELIMITER + text);
    }

    /**
     * @param message
     *            the message as a string, that should send.
     * @return the result of the call
     * @throws UnknownHostException
     * @throws IOException
     */
    private boolean sendMessage(String message) {

        StringBuilder result = new StringBuilder();

        try {
            Socket client = getSocket();

            PrintStream os = new PrintStream(client.getOutputStream(), false, CHARSET_UTF_8);
            os.println(message);
            LOGGER.info("Send message to AUT:" + message);
            os.flush();
            BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream(), CHARSET_UTF_8));

            int c;
            while ((c = in.read()) != -1) {
                result.append((char) c);
            }
            String myMessage = result.toString();
            if (myMessage.indexOf("ERROR ") > -1) {
                LOGGER.error("Fails: " + myMessage);
                throw new RuntimeException("Message: " + message + " fails with: " + myMessage);
            }

            client.close();

        } catch (UnknownHostException e) {
            LOGGER.error("SendMessage Host not Found", e);
        } catch (IOException e) {
            LOGGER.error("Send Message IOException ", e);
        }
        if (result.toString().startsWith("true")) {
            return true;
        }
        return false;
    }

    /**
     * This method searches for the FitNesse-server for the project. It searches
     * on the FitNesse-server, that is running under the configured port, after
     * the main page of project. If the main-page is found, than it returns
     * true, else false.
     * 
     * @param port
     *            of the fitNesseServer
     * @param projectName
     *            the name of the project.
     * @return true if a FitNesse-server is for this project.
     */
    public boolean isFitNesseProjectServerRunning(String port, String projectName) {

        HttpGet httpGet = new HttpGet(
                getFitnesseUrl(port) + projectName + "?search&searchString=" + projectName + "&searchType=title");
        httpGet.setHeader("Content-Type", "application/json");

        String strOfWikiPages;

        try {
            DefaultHttpClient defaultHttpClient = new DefaultHttpClient();

            HttpResponse httpResponse = defaultHttpClient.execute(httpGet);
            strOfWikiPages = (new BasicResponseHandler()).handleResponse(httpResponse);
            String searchString = "<a href=\"" + projectName + "\">" + projectName + "</a>";
            if (strOfWikiPages.contains(searchString)) {
                LOGGER.trace("Server is running");
                return true;
            }
        } catch (Exception e) {

            LOGGER.error("No FitNesse found in: " + getFitnesseUrl(port) + projectName + "\n" + e.getMessage());
            return false;
        }
        return false;
    }

    /**
     * Looks up the TestProjectConfiguration to build the Fitnesse URL.
     * 
     * @param port
     *            the port of the project
     * @return the url to the fitnesse server.
     */
    private String getFitnesseUrl(String port) {
        StringBuilder sb = new StringBuilder();
        sb.append("http://localhost:").append(port).append("/");
        return sb.toString();
    }

    /**
     * Starts the AUT, an Eclipse e4 RCP executable. The Config is read and
     * extended with the SWTBot Agent of the TestEditor. This one launches the
     * Application in a Testmode.
     * 
     * @param applicationPath
     *            to the executable
     * @throws Exception
     *             on Test execution
     */
    public void startApplication(String applicationPath) throws Exception {
        try {
            if (System.getProperty("aut.workspace.path") == null) {
                LOGGER.error("Workspace path <aut.workspace.path> for the aut is not set.");
            }
            waitUntilPreviousLaunchIsFinished();
            runningApp = true;
            prepareAUTWorkspace();
            if (!new File(applicationPath).exists()) {
                LOGGER.info("AUT not found at: " + applicationPath);
                throw new StopTestException("Executable of the AUT not found.");
            }
            LOGGER.info("AUT found at: " + applicationPath);

            LOGGER.info("java.class.path : " + System.getProperty("java.class.path"));

            String swtBotAgnetBundlePath = System.getProperty("SWT_BOT_AGENT_BUNDLE_PATH");

            String autConfiguration = createAUTConfiguration(applicationPath, swtBotAgnetBundlePath);
            launchApplicationCommandList = new ArrayList<String>();

            // if the AUT is a MAC OS X binary
            if (applicationPath.endsWith(".app")) {
                launchApplicationCommandList.add("open");
                launchApplicationCommandList.add(applicationPath);
                launchApplicationCommandList.add("--args");
            }
            // for all other binaries (Linux, Windows)
            else {
                launchApplicationCommandList.add(applicationPath);
            }

            launchApplicationCommandList.add("-clean");
            launchApplicationCommandList.add("-application");
            launchApplicationCommandList.add("org.testeditor.agent.swtbot.TestEditorSWTBotAgent");
            launchApplicationCommandList.add("-aut");
            launchApplicationCommandList.add("org.eclipse.e4.ui.workbench.swt.E4Application");
            launchApplicationCommandList.add("-data");
            launchApplicationCommandList.add(getWorkspacePath());

            launchApplicationCommandList.add("-nl");
            launchApplicationCommandList.add("de_de");
            launchApplicationCommandList.add("-configuration");
            launchApplicationCommandList.add(autConfiguration);
            createAndLaunchProcess();
        } catch (Exception exp) {
            LOGGER.error("Error Test execution: ", exp);
            throw new StopTestException(exp);
        }
    }

    /**
     * Creates and launches the Process for the AUT.
     * 
     * @throws Exception
     *             on problems to create the AUT process.
     */
    private void createAndLaunchProcess() throws Exception {
        LOGGER.trace("Start List: " + Arrays.toString(launchApplicationCommandList.toArray()));
        ProcessBuilder builder = new ProcessBuilder(launchApplicationCommandList);
        builder.redirectErrorStream(true);
        LOGGER.info("Start SWT-app-under-test");
        process = builder.start();
        createAndRunLoggerOnStream(process.getInputStream(), false);
        createAndRunLoggerOnStream(process.getErrorStream(), true);
        LOGGER.info("Output from SWT-app-under-test");
        boolean launched = false;
        int timeOut = 0;
        while (!launched) {
            try {
                Thread.sleep(200);
                LOGGER.info("waiting for launch");
                launched = isLaunched();
                timeOut++;
                if (timeOut > 200) {
                    stopApplication();
                    throw new StopTestException("Time out launching AUT.");
                }
            } catch (InterruptedException e) {
                LOGGER.error("startApplication InterruptedException: ", e);
            }
        }
        LOGGER.info("SWT-app-under-test is ready for test");
        sendMessage("setTestName" + COMMAND_DELIMITER + testName);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            LOGGER.error("startApplication InterruptedException: ", e);
        }
    }

    /**
     * Waits until a previous launch is terminated.
     * 
     * @throws InterruptedException
     *             while waiting.
     * 
     */
    protected void waitUntilPreviousLaunchIsFinished() throws InterruptedException {
        LOGGER.info("Already a process running? " + runningApp);
        int count = 0;
        while (runningApp) {
            Thread.sleep(100);
            count++;
            if (count > 100) {
                LOGGER.error(">>>>>>> Old process blocks AUT start for 10 seconds. Giving up for test: " + testName
                        + ".");
                try {
                    List<String> allLines = Files.readAllLines(
                            new File(new File(getWorkspacePath(), ".metadata"), ".log").toPath(),
                            Charset.forName("UTF-8"));
                    LOGGER.error("AUT .log content:");
                    for (String string : allLines) {
                        LOGGER.error(string);
                    }
                } catch (Exception e) {
                    LOGGER.error("Error reading .log of AUT.", e);
                } finally {
                    stopApplication();
                }
            }
        }
    }

    /**
     * Marks application as stopped.
     * 
     * @return true.
     */
    public boolean markApplicationStopped() {
        runningApp = false;
        return true;
    }

    /**
     * Executes the AUT for local Debugging outsite the TE Context as an JUnit
     * Test.
     * 
     * @param applicationPath
     *            to AUT
     * @param workspace
     *            the workspace for the testeditor_aut
     * @param bundleDir
     *            Path to the Parent directory of the SWTBot agent server
     *            bundle.
     * @throws Exception
     *             on Test execution
     */
    protected void startJUnitApplication(String applicationPath, String workspace, String bundleDir)
            throws Exception {

        try {
            String autConfiguration = createAUTConfiguration(applicationPath, bundleDir);
            ArrayList<String> list = new ArrayList<String>();
            list.add(applicationPath);
            list.add("-clean");
            list.add("-application");
            list.add("org.testeditor.agent.swtbot.TestEditorSWTBotAgent");
            list.add("-aut");
            list.add("org.eclipse.e4.ui.workbench.swt.E4Application");
            list.add("-data");
            list.add(workspace);
            list.add("-nl");
            list.add("de_de");
            list.add("-configuration");
            list.add(autConfiguration);
            ProcessBuilder builder = new ProcessBuilder(list);
            builder.redirectErrorStream(true);
            LOGGER.info("Start SWT-app-under-test");
            process = builder.start();
            createAndRunLoggerOnStream(process.getInputStream(), false);
            createAndRunLoggerOnStream(process.getErrorStream(), true);
            LOGGER.info("Output from SWT-app-under-test");
            boolean launched = false;
            while (!launched) {
                try {
                    Thread.sleep(100);
                    LOGGER.info("waiting for launch");
                    launched = isLaunched();
                } catch (InterruptedException e) {
                    LOGGER.error("startApplication InterruptedException: ", e);
                }
            }
            LOGGER.info("SWT-app-under-test is ready for test");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                LOGGER.error("startApplication InterruptedException: ", e);
            }
        } catch (Exception exp) {
            LOGGER.error("Error Test execution: ", exp);
            throw exp;
        }
    }

    /**
     * Cleans the Workspace of the AUT and creates a demo Project.
     * 
     * @throws IOException
     *             on reset the workspace.
     * @throws URISyntaxException
     *             on reset the workspace.
     */
    private void prepareAUTWorkspace() throws IOException, URISyntaxException {

        File wsPathFile = new File(getWorkspacePath());
        Path wsPath = wsPathFile.toPath();
        if (wsPathFile.exists()) {
            Files.walkFileTree(wsPath, getDeleteFileVisitor());
            LOGGER.info("Removed AUT_WS: " + getWorkspacePath());
        }
        Files.createDirectory(wsPath);
        Map<String, String> env = new HashMap<String, String>();
        env.put("create", "true");
        FileSystem fs = FileSystems.newFileSystem(getClass().getResource("/DemoWebTests.zip").toURI(), env);
        Iterable<Path> rootDirectories = fs.getRootDirectories();
        for (Path root : rootDirectories) {
            DirectoryStream<Path> directoryStream = Files.newDirectoryStream(root);
            for (Path path : directoryStream) {
                if (path.getFileName().startsWith("DemoWebTests.zip")) {
                    LOGGER.info("Found DemoWebTest.");
                    Files.copy(path, Paths.get(wsPath.toString(), "DemoWebTests.zip"));
                    URI uriDemoZip = new URI("jar:" + Paths.get(wsPath.toString(), "/DemoWebTests.zip").toUri());
                    LOGGER.info(uriDemoZip);
                    FileSystem zipFs = FileSystems.newFileSystem(uriDemoZip, env);
                    copyFolder(zipFs.getPath("/"), Paths.get(getWorkspacePath()));
                    zipFs.close();
                }
            }
        }
        fs.close();
        LOGGER.info("Created Demoproject in: " + getWorkspacePath());
    }

    /**
     * copies the directories.
     * 
     * @param src
     *            source-directory
     * @param dest
     *            destination-directory
     * @throws IOException
     *             IOException
     */
    private void copyFolder(Path src, Path dest) throws IOException {
        if (Files.isDirectory(src)) {
            // if directory not exists, create it
            if (!Files.exists(dest)) {
                Files.createDirectory(dest);
            }
            DirectoryStream<Path> directoryStream = Files.newDirectoryStream(src);
            for (Path path : directoryStream) {
                Path srcFile = path;
                Path destFile = Paths.get(dest.toString() + "/" + path.getFileName());
                copyFolder(srcFile, destFile);
            }
        } else {
            Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
        }
    }

    /**
     * Creates a thread to log the content of the input stream. This thread is
     * started after creation.
     * 
     * @param inputStream
     *            to piped to the logger.
     * @param errorStream
     *            if true the logger uses the error level in other cases info.
     */
    private void createAndRunLoggerOnStream(final InputStream inputStream, final boolean errorStream) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                char[] cbuf = new char[8192];
                int len = -1;
                try {
                    InputStreamReader reader = new InputStreamReader(inputStream, CHARSET_UTF_8);
                    while ((len = reader.read(cbuf)) > 0) {
                        if (errorStream) {
                            LOGGER.error(new String(cbuf, 0, len));
                        } else {
                            LOGGER.info(new String(cbuf, 0, len));
                        }
                    }
                } catch (IOException e) {
                    LOGGER.debug("Error reading remote Process Stream", e);
                }
            }
        }).start();
    }

    /**
     * copies the original config.ini of the SWT-app-under-test in the
     * temporary-directory of the os and adds a reference to the SWTBotAgent.
     * This is necessary to start the application with the SWTBotAgent.
     * 
     * 
     * @param applicationPath
     *            the path of the application.
     * @param swtBotAgentBundlePath
     *            Directory to the TestEditor bundle directory.
     * @return the absolutPath to the directory of the config.ini of the
     *         application.
     * @throws IOException
     *             on creating the property file.
     */
    private String createAUTConfiguration(String applicationPath, String swtBotAgentBundlePath) throws IOException {
        FileInputStream fileInputStreamConfig = null;
        FileOutputStream fileOutputStream = null;
        Properties properties = new Properties();
        String result = null;
        fileInputStreamConfig = new FileInputStream(lookUpConfigIni(applicationPath));
        properties.load(fileInputStreamConfig);
        fileInputStreamConfig.close();
        String bundles = properties.getProperty("osgi.bundles");
        LOGGER.info("Bundle: " + swtBotAgentBundlePath);
        // begin; This part is just for considering the testing of an swt
        // application with the test-editor started from IDE
        if (new File(swtBotAgentBundlePath).isDirectory()) {
            LOGGER.info("Directory found for bundle: " + swtBotAgentBundlePath);
            File srcBundleDir = new File(swtBotAgentBundlePath + File.separator + "target");
            LOGGER.info("Directory found for source bundle: " + srcBundleDir + " -> " + srcBundleDir.exists());
            File jarBundle = srcBundleDir.listFiles(getSWTBotAgentFilter())[0];
            swtBotAgentBundlePath = jarBundle.getAbsolutePath();
        }
        // end;
        LOGGER.info("Found Path to Agent Bundle: " + swtBotAgentBundlePath);
        properties.setProperty("osgi.bundles", bundles + ",reference:file:" + swtBotAgentBundlePath);
        File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "configuration");
        if (!file.exists()) {
            if (!file.mkdir()) {
                return "";
            }
        }
        result = file.getAbsolutePath() + File.separator + "config.ini";
        fileOutputStream = new FileOutputStream(result);
        properties.store(fileOutputStream, "Changed for TestEditor run.");
        fileOutputStream.close();
        LOGGER.info("New congfig.ini: " + result);
        return new File(result).getParentFile().getAbsolutePath();
    }

    /**
     * Look up for the config.ini of the AUT. On Linux and Windows an RCP
     * Application has the config.ini related to the
     * binary/configuration/config.ini. On MacOs it is
     * ../../../configuration/config.ini
     * 
     * @param applicationPath
     *            to the executable
     * @return a File to an existing file.
     */
    private File lookUpConfigIni(String applicationPath) {
        String path = new File(applicationPath).getParentFile().getAbsolutePath();
        LOGGER.info("Using Applicationpath: " + applicationPath + " with app directory: " + path);
        File linuxOrWinFile = new File(path + File.separator + "configuration" + File.separator + "config.ini");
        if (linuxOrWinFile.exists()) {
            return linuxOrWinFile;
        } else {
            return new File(path + "/../../../configuration/config.ini");
        }
    }

    /**
     * FileFilter to find the SWTBotAgent Bundle.
     * 
     * @return true if there is a an SWTBot bundle
     */
    protected FileFilter getSWTBotAgentFilter() {
        return new FileFilter() {

            @Override
            public boolean accept(File pathname) {
                if (pathname.getName().startsWith("org.testeditor.agent.swtbot")) {
                    return true;
                }
                return false;
            }
        };
    }

    /**
     * Returns true if the application is launched.
     * 
     * @return true, if the server is ready.
     */
    private boolean isLaunched() {
        try {
            Socket client = getSocket();
            LOGGER.info("Is server ready for " + testName + "?");
            PrintStream os = new PrintStream(client.getOutputStream(), false, CHARSET_UTF_8);
            os.println("isLaunched");
            os.flush();
            BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream(), CHARSET_UTF_8));
            String s = in.readLine();
            LOGGER.info(s);
            client.close();
            return Boolean.valueOf(s);
        } catch (UnknownHostException e) {
            LOGGER.error("isLaunched UnknownHostException: ", e);
        } catch (ConnectException e) {
            LOGGER.trace("Server not available.");
        } catch (IOException e) {
            LOGGER.error("isLaunched IOException: ", e);
        }
        return false;
    }

    /**
     * 
     * @return Socket connected to the SWTBotAgent.
     * @throws UnknownHostException
     *             by socket
     * @throws IOException
     *             by socket
     */
    private Socket getSocket() throws UnknownHostException, IOException {
        return new Socket(AGENT_HOST, AGENT_PORT);
    }

    /**
     * 
     * @param elementKey
     *            the key for the element-list
     * 
     * @return the value to the key in the element-list, if found, else the key.
     */
    private String getLocator(String elementKey) {
        String locator = getLocatorWrapped(elementKey);
        if (locator == null) {
            return elementKey;
        }
        return locator;
    }

    /**
     * 
     * @param elementKey
     *            the key for the element-list
     * @return the value to the key, if found.
     */
    private String getLocatorWrapped(String elementKey) {
        String locator = null;
        try {
            locator = elementListService.getValue(elementKey);
            return locator;
        } catch (ElementKeyNotFoundException e) {
            String message = "The specified Key for the Gui-Element \"" + elementKey + "\" could not be found!";
            LOGGER.info(message, e);
            return null;
        }
    }

    @Override
    public void tearDown() {
        LOGGER.info("TearDown to cleanup the AUT.");
        stopApplication();
        //return true;
    }

    @Override
    public String getTestName() {
        return testName;
    }

    @Override
    public void setTestName(String testName) {
        this.testName = testName;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.testeditor.fixture.core.interaction.Fixture#preInvoke(java.lang.
     * reflect .Method, java.lang.Object, java.lang.Object[])
     */
    @Override
    public void preInvoke(Method method, Object instance, Object... convertedArgs)
            throws InvocationTargetException, IllegalAccessException {

        String label = PerformanceLogHandler.getLabel(method, convertedArgs);

        javaMon = MonitorFactory.start(label);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.testeditor.fixture.core.interaction.Fixture#postInvoke(java.lang.
     * reflect.Method, java.lang.Object, java.lang.Object[])
     */
    @Override
    public void postInvoke(Method method, Object instance, Object... convertedArgs)
            throws InvocationTargetException, IllegalAccessException {

        javaMon.stop();

    }

    /**
     * This method writes the collected logdata at the end of each test.
     */
    public void writePerformanceLog() {

        try {

            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("TOTAL_TIME_FOR_INDIVIDUAL_TEST:" + MonitorFactory.getRootMonitor().getTotal());
            }

            new PerformanceLogHandler().logPerformanceData(getTestName());

            // resetting logdata for the last called Test
            javaMon.reset();

        } catch (Exception e) {
            LOGGER.error(e.getMessage());
        }
    }

    /**
     * Returns the path to the Workspace of the AUT. Relative paths are
     * converted to direct paths.
     * 
     * @return the path to the workspace of the AUT as String.
     * @throws IOException
     *             on looking up the real path.
     */
    public String getWorkspacePath() throws IOException {
        String workspacePath = System.getProperty("aut.workspace.path");

        if (workspacePath == null) {
            workspacePath = "@user.home/.testeditor_aut";
        }

        return new File(workspacePath).getCanonicalPath();
    }

    /**
     * 
     * @param proprtyFileName
     *            of the property file.
     * @param propertyKey
     *            the key of the property wich should be checked in the config.
     * @param propertyValue
     *            the value of the property to be mached to the value of the
     *            property key.
     * @return true if the value according to the key in the files is equals to
     *         propertyValue.
     * @throws IOException
     *             on error reading proprty file
     */
    public boolean checkInProprtyValue(String proprtyFileName, String propertyKey, String propertyValue)
            throws IOException {
        Properties properties = new Properties();
        FileInputStream inputStream = new FileInputStream(proprtyFileName);
        properties.load(inputStream);
        inputStream.close();
        boolean found = properties.get(propertyKey).equals(propertyValue);
        LOGGER.info("Property search in " + proprtyFileName + " with key " + propertyKey + " and value: "
                + propertyValue + " is: " + found);
        return found;
    }

    /**
     * Creates TestStructure Files in the filesystem of a fitnesse backend
     * system. This method doesn't use the api for that and does no
     * notifications to the test-editor or fitnsse server.
     * 
     * @param destinationTestStructure
     *            full name of the new one
     * @return true on success
     * @throws IOException
     *             on creation error.
     */
    public boolean createTestStructureFiles(String destinationTestStructure) {
        String[] tsNameParts = destinationTestStructure.split("\\.");

        try {
            String destPath = getWorkspacePath() + File.separator + tsNameParts[0] + File.separator + "FitNesseRoot"
                    + File.separator
                    + destinationTestStructure.replaceAll("\\.", Matcher.quoteReplacement(File.separator));
            Path tsDir = Files.createDirectories(Paths.get(destPath));
            LOGGER.trace("Created: " + tsDir.toAbsolutePath());
            String xml = "<?xml version=\"1.0\"?><properties><Edit>true</Edit><Files>true</Files><Properties>true</Properties><RecentChanges>true</RecentChanges><Refactor>true</Refactor><Search>true</Search><Test/><Versions>true</Versions><WhereUsed>true</WhereUsed></properties>";
            Files.write(Paths.get(destPath, "properties.xml"), xml.getBytes());
            return new File(tsDir.toFile(), "content.txt").createNewFile();
        } catch (Exception e) {
            LOGGER.error("Error creating testobject from " + destinationTestStructure, e);
        }
        return false;
    }

    /**
     * Waits until a button is enabled.
     * 
     * @param locator
     *            of the button.
     * @param timeOut
     *            to wait for the button. the time is in seconds.
     * @return true if it was possible to click on the button.
     */
    public boolean waitForButtonAndClick(String locator, int timeOut) {
        int timeOutMax = timeOut * 1000;
        int timeOutCounter = 0;
        while (!isButtonEnabled(locator) & timeOutMax > timeOutCounter) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                LOGGER.error("Interruption by waiting for ui elment,", e);
            }
            timeOutCounter = timeOutCounter + 100;
        }
        return clickButton(locator);
    }

    /**
     * Waits until a button is enabled. The timeout for waiting is 30 seconds.
     * 
     * @param locator
     *            of the button.
     * @return true if it was possible to click on the button.
     */
    public boolean waitForButtonAndClick(String locator) {
        return waitForButtonAndClick(locator, 30);
    }

    /**
     * Selects an entry in the active auto complete field.
     * 
     * @param item
     *            String to be selected in the auto complete list.
     * @return the result of the message.
     */
    public boolean selectElementInAtuocompleteWidget(String item) {
        return sendMessage("selectElementInAtuocompleteWidget" + COMMAND_DELIMITER + item);
    }

    /**
     * This method checks if a specific line contains a text. Line numbers are
     * starting at one.
     * 
     * @param testFilePath
     *            path to the source file, starting from "aut.workspace.path",
     *            comma separated.
     * @param text
     *            the text to search for
     * @param line
     *            line number starting at 1
     * @return true if the text is found in the line
     * @throws StopTestException
     *             will be thrown if the "aut.workspace.path" system variable is
     *             not set or line is zero
     * @throws IOException
     *             will be thrown if the file not exist
     */
    public boolean checkTextInCodeLine(String testFilePath, String text, int line)
            throws StopTestException, IOException {
        String workspacePath = System.getProperty("aut.workspace.path");
        if (workspacePath == null || workspacePath.equals("")) {
            LOGGER.error("aut.workspace.path not set");
            throw new StopTestException("aut.workspace.path not set");
        }
        if (line == 0) {
            throw new StopTestException("line 0 not exist");
        }

        return sourceList(workspacePath, testFilePath).get(line - 1).contains(text);
    }

    /**
     * This method checks if a specific line dosn't contain a text. Line numbers
     * are starting at one.
     * 
     * @param testFilePath
     *            path to the source file, starting from "aut.workspace.path",
     *            comma separated.
     * @param text
     *            the text thats not in the line
     * @param line
     *            line number starting at 1
     * @return true if the text is found in the line
     * @throws StopTestException
     *             will be thrown if the "aut.workspace.path" system variable is
     *             not set or line is zero
     * @throws IOException
     *             will be thrown if the file not exist
     */
    public boolean checkNotTextInCodeLine(String testFilePath, String text, int line)
            throws StopTestException, IOException {
        String workspacePath = System.getProperty("aut.workspace.path");
        if (workspacePath == null || workspacePath.equals("")) {
            LOGGER.error("aut.workspace.path not set");
            throw new StopTestException("aut.workspace.path not set");
        }
        if (line == 0) {
            throw new StopTestException("line 0 not exist");
        }

        return !sourceList(workspacePath, testFilePath).get(line - 1).contains(text);
    }

    /**
     * Opens a file in the workspace and returns the source as a List.
     * 
     * @param directory
     *            start path parameter
     * @param testFilePath
     *            comma separated path to file path
     * @return a list of all source lines
     * @throws IOException
     *             if file not exist
     */
    private List<String> sourceList(String directory, String testFilePath) throws IOException {
        String[] folder = testFilePath.split(",");
        directory += File.separator + folder[0] + File.separator + "FitNesseRoot"; // Project
        // name
        // and
        // FitNsesseRoot
        for (String string : folder) {
            directory += File.separator + string;
        }
        directory += File.separator + "content.txt";
        File dirFile = new File(directory);
        Path path = dirFile.toPath();
        LOGGER.warn("PATH " + path.toString() + "  " + path.toFile().exists() + "---" + Charset.defaultCharset());
        List<String> lines = Files.readAllLines(path, Charset.defaultCharset());
        return lines;
    }

    /**
     * Copy a File or a Directory inside the AUT workspace. Existing target
     * files / Directories are overwritten without warnings.
     *
     * @param relSourcePath
     *            the workspace relative path of the source file or directory to
     *            copy
     * @param relTargetPath
     *            the workspace relative path of the target file or directory
     */
    public void copyInWorkspace(String relSourcePath, String relTargetPath) {

        LOGGER.info("kopiere. " + relSourcePath + " nach " + relTargetPath);

        File workspaceDir;
        try {
            workspaceDir = new File(getWorkspacePath());
        } catch (IOException e1) {
            String msg = "cannot find workspacePath";
            LOGGER.error(msg);
            throw new StopTestException(msg);
        }
        File source = new File(workspaceDir, relSourcePath);
        File target = new File(workspaceDir, relTargetPath);
        Path sourcePath = Paths.get(source.getAbsolutePath());
        Path targetPath = Paths.get(target.getAbsolutePath());

        if (!source.exists()) {
            String msg = "cannot copy '" + source + "': File does not exist";
            LOGGER.error(msg);
            throw new StopTestException(msg);
        }
        if (!source.canRead()) {
            String msg = "cannot copy '" + source + "': File cannot be read";
            LOGGER.error(msg);
            throw new StopTestException(msg);
        }

        if (source.isDirectory()) {
            try {
                copyFolder(sourcePath, targetPath);
            } catch (IOException e) {
                String msg = "cannot copy directory '" + source + "' to '" + target + "'";
                LOGGER.error(msg, e);
                throw new StopTestException(msg, e);
            }
        } else {
            try {
                Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException e) {
                String msg = "cannot copy directory '" + source + "' to '" + target + "'";
                LOGGER.error(msg, e);
                throw new StopTestException(msg, e);
            }
        }

    }

    /**
     * delete a given file or directory in the workspace
     * 
     * @param relTargetPath
     *            the workspace relative path of the source file or directory to
     *            delete (recursively in the later case)
     */
    public void deleteInWorkspace(String relTargetPath) {
        File workspaceDir;
        try {
            workspaceDir = new File(getWorkspacePath());
        } catch (IOException e1) {
            String msg = "cannot find workspacePath";
            LOGGER.error(msg);
            throw new StopTestException(msg);
        }
        File target = new File(workspaceDir, relTargetPath);

        if (target.exists()) {
            if (target.isDirectory()) {
                deleteFolder(target);
            } else {
                try {
                    Files.delete(target.toPath());
                } catch (IOException e) {
                    String msg = "cannot delete file '" + target + "'";
                    LOGGER.error(msg, e);
                    throw new StopTestException(msg, e);
                }
            }
        }

    }

    /**
     * Deletes folder recursively.
     * 
     * @param target
     *            to be deleted.
     */
    private void deleteFolder(File target) {
        List<File> files = Arrays.asList(target.listFiles());
        for (File file : files) {
            if (file.isFile()) {
                try {
                    Files.delete(file.toPath());
                } catch (IOException e) {
                    String msg = "cannot delete file '" + target + "'";
                    LOGGER.error(msg, e);
                    throw new StopTestException(msg, e);
                }
            } else {
                deleteFolder(file);
            }
        }
        try {
            Files.delete(target.toPath());
        } catch (IOException e) {
            String msg = "cannot delete file '" + target + "'";
            LOGGER.error(msg, e);
            throw new StopTestException(msg, e);
        }
    }

    /**
     * create or overwrite a file in the workspace and fill it with the given
     * content.
     * 
     * @param relTargetPath
     *            the workspace relative path of the target file to create
     * @param content
     *            the content of the new file
     */
    public void createFileInWorkspace(String relTargetPath, String content) {
        File workspaceDir;
        try {
            workspaceDir = new File(getWorkspacePath());
        } catch (IOException e1) {
            String msg = "cannot find workspacePath";
            LOGGER.error(msg);
            throw new StopTestException(msg);
        }
        if (relTargetPath.contains("/")) {
            try {
                Files.createDirectories(Paths.get(workspaceDir.getAbsolutePath(),
                        relTargetPath.substring(0, relTargetPath.lastIndexOf("/"))));
            } catch (IOException e) {
                String msg = "cannot create file '" + relTargetPath.substring(0, relTargetPath.lastIndexOf("/"))
                        + "'";
                LOGGER.error(msg, e);
                throw new StopTestException(msg, e);
            }
        }
        File target = new File(workspaceDir, relTargetPath);

        deleteInWorkspace(relTargetPath);

        try {
            PrintWriter pw = new PrintWriter(target);
            pw.print(content);
            pw.close();
        } catch (FileNotFoundException e) {
            String msg = "cannot create file '" + target + "'";
            LOGGER.error(msg, e);
            throw new StopTestException(msg, e);
        }

    }

    public boolean checkValueInDropDownBox(String dropDownBoxID, String value) {
        return sendMessage("checkDropDownContains" + COMMAND_DELIMITER + getLocator(dropDownBoxID)
                + COMMAND_DELIMITER + value);
    }

}