package ch.vorburger.webdriver.runner.core.providers; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.internal.WrapsDriver; import org.openqa.selenium.internal.WrapsElement; import org.openqa.selenium.support.events.WebDriverEventListener; /** * WebDriver Delegate helper. * * Implementation for the correct handling for the various WebDriver extension * interfaces (JavascriptExecutor, TakesScreenshot, HasInputDevices, HasTouchScreen; * Rotatable, BrowserConnection, WebStorage, LocationContext, LocationListener, * ApplicationCache; FindsBy* etc.) is "strongly inspired" (erm, mostly * copy/pasted) from the EventFiringWebDriver. * * Shame such a helper/util class is not already included in WebDriver core. * @see https://code.google.com/p/selenium/issues/detail?id=2512 * * @author Michael Vorburger */ public abstract class DelegatingWebDriver implements WebDriver, WrapsDriver { // intentionally private and not protected, because all code should go through getWrappedDriver() private final WebDriver delegate; protected DelegatingWebDriver(final WebDriver delegate) { // copy/pasted from EventFiringWebDriver Class<?>[] allInterfaces = extractInterfaces(delegate); this.delegate = (WebDriver) Proxy.newProxyInstance( WebDriverEventListener.class.getClassLoader(), allInterfaces, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("getWrappedDriver".equals(method.getName())) { return delegate; } try { return method.invoke(delegate, args); } catch (InvocationTargetException e) { onExceptionFromAdditionalInterfaceProxyInvocation(e); throw e.getTargetException(); } } }); } // copy/pasted from EventFiringWebDriver protected Class<?>[] extractInterfaces(Object object) { Set<Class<?>> allInterfaces = new HashSet<Class<?>>(); allInterfaces.add(WrapsDriver.class); if (object instanceof WebElement) { allInterfaces.add(WrapsElement.class); } extractInterfaces(allInterfaces, object.getClass()); return allInterfaces.toArray(new Class<?>[allInterfaces.size()]); } // copy/pasted from EventFiringWebDriver protected void extractInterfaces(Set<Class<?>> addTo, Class<?> clazz) { if (Object.class.equals(clazz)) { return; // Done } Class<?>[] classes = clazz.getInterfaces(); addTo.addAll(Arrays.asList(classes)); extractInterfaces(addTo, clazz.getSuperclass()); } protected void onExceptionFromAdditionalInterfaceProxyInvocation(InvocationTargetException e) { // dispatcher.onException(e.getTargetException(), driver); } @Override public WebDriver getWrappedDriver() { return delegate; } public void get(String url) { getWrappedDriver().get(url); } public String getCurrentUrl() { return getWrappedDriver().getCurrentUrl(); } public String getTitle() { return getWrappedDriver().getTitle(); } public List<WebElement> findElements(By by) { return getWrappedDriver().findElements(by); } public WebElement findElement(By by) { return getWrappedDriver().findElement(by); } public String getPageSource() { return getWrappedDriver().getPageSource(); } public void close() { getWrappedDriver().close(); } public void quit() { getWrappedDriver().quit(); } public Set<String> getWindowHandles() { return getWrappedDriver().getWindowHandles(); } public String getWindowHandle() { return getWrappedDriver().getWindowHandle(); } public TargetLocator switchTo() { return getWrappedDriver().switchTo(); } public Navigation navigate() { return getWrappedDriver().navigate(); } public Options manage() { return getWrappedDriver().manage(); } }