package org.jboss.arquillian.drone.webdriver.binary.process;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.arquillian.spacelift.Spacelift;
import org.arquillian.spacelift.execution.Execution;
import org.arquillian.spacelift.process.Command;
import org.arquillian.spacelift.process.CommandBuilder;
import org.arquillian.spacelift.process.ProcessResult;
import org.arquillian.spacelift.task.os.CommandTool;
import org.jboss.arquillian.core.api.InstanceProducer;
import org.jboss.arquillian.core.api.annotation.ApplicationScoped;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.core.api.annotation.Observes;
import org.jboss.arquillian.drone.webdriver.binary.handler.BinaryHandler;
import org.jboss.arquillian.drone.webdriver.binary.handler.ChromeDriverBinaryHandler;
import org.jboss.arquillian.drone.webdriver.binary.handler.EdgeDriverBinaryHandler;
import org.jboss.arquillian.drone.webdriver.binary.handler.FirefoxDriverBinaryHandler;
import org.jboss.arquillian.drone.webdriver.binary.handler.InternetExplorerBinaryHandler;
import org.jboss.arquillian.drone.webdriver.binary.handler.PhantomJSDriverBinaryHandler;
import org.jboss.arquillian.drone.webdriver.factory.BrowserCapabilitiesList;
import org.jboss.arquillian.drone.webdriver.utils.Validate;
import org.jboss.arquillian.test.spi.event.suite.AfterSuite;
import org.openqa.selenium.remote.DesiredCapabilities;
/**
* Is responsible for launching and stopping selenium server binary
*/
public class SeleniumServerExecutor {
private Logger log = Logger.getLogger(SeleniumServerExecutor.class.toString());
@Inject
@ApplicationScoped
private InstanceProducer<SeleniumServerExecution> seleniumServerExecutionInstanceProducer;
/**
* Runs an instance of Selenium Server
*/
public void startSeleniumServer(@Observes StartSeleniumServer startSeleniumServer) {
String browser = startSeleniumServer.getBrowser();
String seleniumServerArgs = startSeleniumServer.getSeleniumServerArgs();
String seleniumServer = startSeleniumServer.getPathToSeleniumServerBinary();
int port = startSeleniumServer.getUrl().getPort();
BinaryHandler browserBinaryHandler = getBrowserBinaryHandler(startSeleniumServer.getCapabilities(), browser);
CommandBuilder javaCommand = new CommandBuilder("java");
if (browserBinaryHandler != null) {
try {
String driverBinary = browserBinaryHandler.checkAndSetBinary(true);
if (!Validate.empty(driverBinary)) {
javaCommand
.parameter(
"-D" + browserBinaryHandler.getSystemBinaryProperty() + "=" + new File(driverBinary)
.getAbsolutePath());
}
} catch (Exception e) {
throw new IllegalStateException(
"Something bad happened when Drone was trying to download and extract driver binary of a browser: "
+ browser
+ "\nFor more information see the cause.", e);
}
}
try {
List<String> parameterList =
new ArrayList<>(Arrays.asList("-jar", seleniumServer, "-port", String.valueOf(port)));
if (seleniumServerArgs != null && !seleniumServerArgs.isEmpty()) {
parameterList.addAll(Arrays.asList(seleniumServerArgs.split(" ")));
}
Command build = javaCommand.parameters(parameterList).build();
SeleniumServerExecution execution = new SeleniumServerExecution().execute(build);
seleniumServerExecutionInstanceProducer.set(execution);
} catch (Exception e) {
throw new IllegalStateException(
"Something bad happened when Drone was trying to run Selenium Server binary: " + seleniumServer
+ " For more information see the cause.", e);
}
}
/**
* Stops an instance of Selenium Server
*/
public void stopSeleniumServer(@Observes AfterSuite afterClass, SeleniumServerExecution seleniumServerExecution) {
seleniumServerExecution.stop();
}
/**
* Returns an instance of a {@link BinaryHandler} according to a given browser
*
* @param browser
* A browser name an associated {@link BinaryHandler} should be returned
*
* @return An instance of a {@link BinaryHandler} according to given browser
*/
private BinaryHandler getBrowserBinaryHandler(DesiredCapabilities capabilities, String browser) {
if (new BrowserCapabilitiesList.Firefox().getReadableName().equals(browser)) {
return new FirefoxDriverBinaryHandler(capabilities);
} else if (new BrowserCapabilitiesList.Edge().getReadableName().equals(browser)) {
return new EdgeDriverBinaryHandler(capabilities);
} else if (new BrowserCapabilitiesList.Chrome().getReadableName().equals(browser)) {
return new ChromeDriverBinaryHandler(capabilities);
} else if (new BrowserCapabilitiesList.InternetExplorer().getReadableName().equals(browser)) {
return new InternetExplorerBinaryHandler(capabilities);
} else if (new BrowserCapabilitiesList.PhantomJS().getReadableName().equals(browser)) {
return new PhantomJSDriverBinaryHandler(capabilities);
}
return null;
}
class SeleniumServerExecution {
private Execution<ProcessResult> server;
SeleniumServerExecution() {
}
SeleniumServerExecution execute(Command command) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1);
log.info("Running Selenium server process: " + command.toString());
server = Spacelift
.task(CommandTool.class)
.command(command)
.interaction(new BinaryInteraction()
.outputPrefix("[Selenium server] ")
.printToOut(".*")
.when(".*Selenium Server is up and running")
.thenCountDown(countDownLatch)
.build())
.execute();
server.registerShutdownHook();
countDownLatch.await(10, TimeUnit.SECONDS);
return this;
}
void stop() {
if (server != null) {
log.info("Stopping selenium server ...");
server.terminate();
}
}
}
}