package org.fluentlenium.configuration;
import org.fluentlenium.utils.ReflectionUtils;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* A simple {@link WebDriverFactory} that create {@link WebDriver} instances using reflection.
*/
public class ReflectiveWebDriverFactory implements WebDriverFactory, ReflectiveFactory, FactoryNames {
protected String name;
protected Object[] args;
protected String webDriverClassName;
protected Class<? extends WebDriver> webDriverClass;
protected boolean available;
/**
* Creates a new reflective web driver factory.
*
* @param name factory name
* @param webDriverClassName web driver class name
* @param args web driver class constructor arguments
*/
public ReflectiveWebDriverFactory(String name, String webDriverClassName, Object... args) {
this.name = name;
this.webDriverClassName = webDriverClassName;
this.args = args;
try {
webDriverClass = (Class<? extends WebDriver>) Class.forName(webDriverClassName);
available = WebDriver.class.isAssignableFrom(webDriverClass);
} catch (ClassNotFoundException e) {
available = false;
}
}
/**
* Creates a new reflective web driver factory.
*
* @param name factory name
* @param webDriverClass web driver class
* @param args web driver class constructor arguments
*/
public ReflectiveWebDriverFactory(String name, Class<? extends WebDriver> webDriverClass, Object... args) {
this.name = name;
this.webDriverClass = webDriverClass;
this.args = args;
webDriverClassName = webDriverClass.getName();
available = WebDriver.class.isAssignableFrom(this.webDriverClass);
}
/**
* Get web driver class.
*
* @return web driver class
*/
public Class<? extends WebDriver> getWebDriverClass() {
return webDriverClass;
}
@Override
public boolean isAvailable() {
return available;
}
/**
* Creates new default capabilities.
*
* @return default capabilities
*/
protected DesiredCapabilities newDefaultCapabilities() {
return null;
}
@Override
public WebDriver newWebDriver(Capabilities capabilities, ConfigurationProperties configuration) {
if (!available) {
throw new ConfigurationException("WebDriver " + webDriverClassName + " is not available.");
}
try {
DesiredCapabilities defaultCapabilities = newDefaultCapabilities();
if (defaultCapabilities != null) {
defaultCapabilities.merge(capabilities);
capabilities = defaultCapabilities;
}
if (capabilities != null && !capabilities.asMap().isEmpty()) {
ArrayList<Object> argsList = new ArrayList<>(Arrays.asList(args));
argsList.add(0, capabilities);
try {
return newInstance(webDriverClass, configuration, argsList.toArray());
} catch (NoSuchMethodException e) { // NOPMD EmptyCatchBlock
// Ignore capabilities.
}
}
return newInstance(webDriverClass, configuration, args);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new ConfigurationException("Can't create new WebDriver instance", e);
}
}
/**
* Creates a new instance of web driver.
*
* @param webDriverClass web driver class
* @param configuration configuration
* @param args web driver class constructor arguments
* @return new web driver instance
* @throws NoSuchMethodException if a matching method is not found.
* @throws IllegalAccessException if this {@code Constructor} object
* is enforcing Java language access control and the underlying
* constructor is inaccessible.
* @throws InstantiationException if the class that declares the
* underlying constructor represents an abstract class.
* @throws InvocationTargetException if the underlying constructor
* throws an exception.
*/
protected WebDriver newInstance(Class<? extends WebDriver> webDriverClass, ConfigurationProperties configuration,
Object... args)
throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
return ReflectionUtils.newInstance(webDriverClass, args);
}
@Override
public String[] getNames() {
List<String> names = new ArrayList<>(Arrays.asList(name));
if (webDriverClass != null) {
names.add(webDriverClass.getName());
names.add(webDriverClass.getSimpleName());
}
return names.toArray(new String[names.size()]);
}
}