org.polimi.zarathustra.webdriver.LocalWebdriverWorker.java Source code

Java tutorial

Introduction

Here is the source code for org.polimi.zarathustra.webdriver.LocalWebdriverWorker.java

Source

/*
 * Copyright 2014 Google Inc. All rights reserved.
 * 
 * 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.polimi.zarathustra.webdriver;

import java.io.BufferedWriter;

import java.io.File;
import java.io.FileWriter;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.w3c.dom.Document;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.Uninterruptibles;

/**
 * A local webdriver worker to run a browser on the local machine.
 */
public final class LocalWebdriverWorker {
    private static final class MonitorThread extends Thread {
        private final long timeout;
        private boolean done = false;
        private final Runnable stopWorkerThread;

        private MonitorThread(int timeoutSeconds, Runnable stopWorkerThread) {
            timeout = timeoutSeconds * 1000;
            this.stopWorkerThread = stopWorkerThread;
        }

        public void done() {
            done = true;
        }

        @Override
        public void run() {
            long deadline = new Date().getTime() + timeout;
            while (true) {
                Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
                if (done) {
                    return;
                }
                if (new Date(deadline).after(new Date())) {
                    stopWorkerThread.run();
                    return;
                }
            }
        }
    }

    private static final int MAX_TIMEOUT_SECONDS = 120;
    private static final int DEFAULT_HARD_LIMIT_TIMEOUT_SECONDS = MAX_TIMEOUT_SECONDS + 5;
    private final int hardLimitTimeoutSeconds;
    private WebDriver driver;

    private final boolean useExplorer;

    public LocalWebdriverWorker() {
        this(false);
    }

    public LocalWebdriverWorker(boolean useExplorer) {
        this(useExplorer, DEFAULT_HARD_LIMIT_TIMEOUT_SECONDS);
    }

    @VisibleForTesting
    LocalWebdriverWorker(boolean useExplorer, int hardLimitTimeoutSeconds) {
        this.useExplorer = useExplorer;
        this.hardLimitTimeoutSeconds = hardLimitTimeoutSeconds;
        resetDriver();
    }

    /**
     * Returns a Document representation of the DOM at the provided url. Before navigating to the url,
     * all cookies are deleted.
     * 
     * @param url The full, absolute URL to fetch the DOM from.
     * @return A well formatted Document.
     */
    public Document getDocument(final String url) {
        MonitorThread monitor = new MonitorThread(hardLimitTimeoutSeconds, new Runnable() {
            @Override
            public void run() {
                driver.quit();
                throw new TimeoutException("Timedout while retrieving DOM for " + url);
            }
        });
        monitor.setDaemon(true);
        driver.manage().deleteAllCookies();
        driver.get(url);
        String page = driver.getPageSource();
        monitor.done();
        Preconditions.checkNotNull(url);
        return WebdriverHelper.getDom(page);
    }

    public Document getDocumentAndStoreSource(final String url, File outputDir, String fileName) {
        MonitorThread monitor = new MonitorThread(hardLimitTimeoutSeconds, new Runnable() {
            @Override
            public void run() {
                driver.quit();
                throw new TimeoutException("Timedout while retrieving DOM for " + url);
            }
        });
        monitor.setDaemon(true);
        driver.manage().deleteAllCookies();
        driver.get(url);
        // TODO(claudio): handle download errors, truncated pages, weird redirects (e.g. opendns)
        String page = driver.getPageSource();
        storeHtmlSource(outputDir, fileName, page);
        monitor.done();
        Preconditions.checkNotNull(url);
        return WebdriverHelper.getDom(page);
    }

    /**
     * Closes down the webdriver browser.
     */
    public void quit() {
        driver.quit();
    }

    public void storeHtmlSource(File outputDir, String fileName, String page) {
        try {
            // Write "page" to file in the default folder (html_sources) */
            File output = new File(outputDir + "/html_sources", fileName.replace(".dom", ".html"));
            String completeName = output.getAbsolutePath();

            BufferedWriter out = new BufferedWriter(new FileWriter(completeName));
            StringBuffer contents = new StringBuffer();
            contents.append(page);
            out.write(contents.toString());
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Resets and create a new browser instance.
     */
    public WebDriver resetDriver() {
        if (useExplorer) {
            DesiredCapabilities caps = DesiredCapabilities.internetExplorer();
            caps.setCapability(CapabilityType.ForSeleniumServer.ENSURING_CLEAN_SESSION, true);
            caps.setCapability("unexpectedAlertBehaviour", "accept");
            caps.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
            driver = new InternetExplorerDriver(caps);
        } else {
            DesiredCapabilities caps = DesiredCapabilities.firefox();
            caps.setCapability(CapabilityType.ForSeleniumServer.ENSURING_CLEAN_SESSION, true);
            driver = new FirefoxDriver(caps);
        }
        driver.manage().timeouts().pageLoadTimeout(MAX_TIMEOUT_SECONDS, TimeUnit.SECONDS);

        // VERY IMPORTANT: wait some time after opening IE, or you'll run into issues.
        Uninterruptibles.sleepUninterruptibly(5, TimeUnit.SECONDS);
        return driver;
    }
}