org.jboss.arquillian.drone.webdriver.factory.remote.reusable.ReusableRemoteWebDriver.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.arquillian.drone.webdriver.factory.remote.reusable.ReusableRemoteWebDriver.java

Source

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2010, Red Hat Middleware LLC, and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jboss.arquillian.drone.webdriver.factory.remote.reusable;

import java.lang.reflect.Field;
import java.net.URL;

import org.openqa.selenium.Capabilities;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.HttpCommandExecutor;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.SessionId;

/**
 * Reusable remote driver provides same functionality like {@link RemoteWebDriver}, but it additionally allows to reuse browser
 * session.
 *
 * Provides reusing of {@link RemoteWebDriver} session by allowing to setup {@link DesiredCapabilities} and {@link SessionId}
 * from previous session.
 *
 * @author <a href="mailto:lryc@redhat.com">Lukas Fryc</a>
 */
public class ReusableRemoteWebDriver extends RemoteWebDriver {

    ReusableRemoteWebDriver() {
    }

    /**
     * Creates the {@link ReusableRemoteWebDriver} from valid {@link RemoteWebDriver} instance.
     *
     * @param remoteWebDriver valid {@link RemoteWebDriver} instance.
     * @return the {@link RemoteWebDriver} wrapped as {@link ReusableRemoteWebDriver}
     */
    public static ReusableRemoteWebDriver fromRemoteWebDriver(RemoteWebDriver remoteWebDriver) {
        return new ReusableRemoteWebDriver(remoteWebDriver);
    }

    /**
     * Reuses browser session using sessionId and desiredCapabilities as fully-initialized {@link Capabilities} object from the
     * previous {@link RemoteWebDriver} session.
     *
     * @param remoteAddress address of the remote Selenium Server hub
     * @param desiredCapabilities fully-initialized capabilities returned from previous {@link RemoteWebDriver} session
     * @param sessionId sessionId from previous {@link RemoteWebDriver} session
     */
    public static ReusableRemoteWebDriver fromReusedSession(URL remoteAddress, Capabilities desiredCapabilities,
            SessionId sessionId) throws UnableReuseSessionException {
        return new ReusableRemoteWebDriver(remoteAddress, desiredCapabilities, sessionId);
    }

    private ReusableRemoteWebDriver(RemoteWebDriver remoteWebDriver) {
        super();
        setCommandExecutor(remoteWebDriver.getCommandExecutor());

        reuseSession(remoteWebDriver.getSessionId(), remoteWebDriver.getCapabilities());
        try {
            checkReusability();
        } catch (UnableReuseSessionException e) {
            throw new IllegalStateException("Reusing RemoteWebDriver session unexpectedly failed", e);
        }
    }

    private ReusableRemoteWebDriver(URL remoteAddress, Capabilities desiredCapabilities, SessionId sessionId)
            throws UnableReuseSessionException {
        super();
        setCommandExecutor(new HttpCommandExecutor(remoteAddress));
        startClient();

        reuseSession(sessionId, desiredCapabilities);
        checkReusability();
    }

    /**
     * Check that reused session can be controlled.
     *
     * If it cannot be controlled (API calls throw exception), throw {@link UnableReuseSessionException}.
     *
     * @throws UnableReuseSessionException
     */
    private void checkReusability() throws UnableReuseSessionException {
        try {
            this.getCurrentUrl();
        } catch (WebDriverException e) {
            throw new UnableReuseSessionException();
        }
    }

    protected final void reuseSession(SessionId sessionId, Capabilities desiredCapabilities) {
        setReusedSessionId(sessionId);
        setReusedCapabilities(desiredCapabilities);
    }

    void setReusedSessionId(SessionId sessionId) {
        Field sessionIdField = getFieldSafely(this, RemoteWebDriver.class, "sessionId");
        writeValueToField(this, sessionIdField, sessionId);
    }

    void setReusedCapabilities(Capabilities capabilities) {
        Field capabilitiesField = getFieldSafely(this, RemoteWebDriver.class, "capabilities");
        writeValueToField(this, capabilitiesField, capabilities);
    }

    private static Field getFieldSafely(Object object, Class<?> clazz, String fieldName) {
        try {
            return clazz.getDeclaredField(fieldName);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    private static void writeValueToField(Object object, Field field, Object value) {
        boolean wasAccessible = field.isAccessible();
        if (!wasAccessible) {
            field.setAccessible(true);
        }
        try {
            field.set(object, value);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
        if (!wasAccessible) {
            field.setAccessible(false);
        }
    }
}