org.suren.autotest.web.framework.selenium.SeleniumEngine.java Source code

Java tutorial

Introduction

Here is the source code for org.suren.autotest.web.framework.selenium.SeleniumEngine.java

Source

/*
 * Copyright 2002-2007 the original author or authors.
 *
 * 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.suren.autotest.web.framework.selenium;

import static org.suren.autotest.web.framework.settings.DriverConstants.DRIVER_CHROME;
import static org.suren.autotest.web.framework.settings.DriverConstants.DRIVER_FIREFOX;
import static org.suren.autotest.web.framework.settings.DriverConstants.DRIVER_HTML_UNIT;
import static org.suren.autotest.web.framework.settings.DriverConstants.DRIVER_IE;
import static org.suren.autotest.web.framework.settings.DriverConstants.DRIVER_OPERA;
import static org.suren.autotest.web.framework.settings.DriverConstants.DRIVER_PHANTOM_JS;
import static org.suren.autotest.web.framework.settings.DriverConstants.DRIVER_SAFARI;
import static org.suren.autotest.web.framework.settings.DriverConstants.ENGINE_CONFIG_FILE_NAME;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.Cookie;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.UnsupportedCommandException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriver.Options;
import org.openqa.selenium.WebDriver.Window;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.opera.OperaDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.safari.SafariDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import org.suren.autotest.web.framework.core.AutoTestException;
import org.suren.autotest.web.framework.data.DynamicData;
import org.suren.autotest.web.framework.settings.DriverConstants;
import org.suren.autotest.web.framework.util.StringUtils;
import org.suren.autotest.web.framework.util.ThreadUtil;
import org.suren.autotest.webdriver.downloader.DriverDownloader;
import org.suren.autotest.webdriver.downloader.DriverMapping;
import org.suren.autotest.webdriver.downloader.PathUtil;

/**
 * ??
 * @author suren
 * @since jdk1.6 2016629
 */
@Component
@Scope(value = "autotest", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SeleniumEngine {
    private static final Logger logger = LoggerFactory.getLogger(SeleniumEngine.class);

    private final Properties enginePro = new Properties(); //??
    private final Map<String, Object> dataMap = new HashMap<String, Object>();

    private Map<String, DesiredCapabilities> engineCapMap = new HashMap<String, DesiredCapabilities>();

    private WebDriver driver;
    private String driverStr;
    private String remoteStr;
    private long timeout;
    private boolean fullScreen;
    private boolean maximize;
    private int width;
    private int height;
    private int toolbarHeight;

    @Autowired
    private List<DynamicData> dynamicDataList;

    public SeleniumEngine() {
    }

    /**
     * ??
     */
    public void initConfig() {
        try {
            ClassLoader classLoader = this.getClass().getClassLoader();

            loadDefaultEnginePath(classLoader, enginePro); //?

            System.getProperties().putAll(enginePro);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    /**
     * ???
     * @param enginePro
     */
    public void beforeStart(Properties enginePro) {
    };

    /**
     * ??
     */
    public void init() {
        initConfig();

        beforeStart(enginePro);

        new CapabilityConfig(engineCapMap, enginePro).config();

        String curDriverStr = getDriverStr();
        DesiredCapabilities capability = engineCapMap.get(curDriverStr);

        if (StringUtils.isNotBlank(getRemoteStr())) {
            try {
                driver = new RemoteWebDriver(new URL(getRemoteStr()), capability);
            } catch (MalformedURLException e) {
                throw new AutoTestException();
            }
        } else if (DRIVER_CHROME.equals(curDriverStr)) {
            driver = new ChromeDriver(capability);
        } else if (DRIVER_IE.equals(curDriverStr)) {
            driver = new InternetExplorerDriver(capability);
        } else if (DRIVER_FIREFOX.equals(curDriverStr)) {
            //         String proFile = System.getProperty("firefox.profile", null);
            //         FirefoxProfile profile = new FirefoxProfile(proFile != null ? new File(proFile) : null);
            //         fireFoxPreSet(profile);
            //         FirefoxOptions firefoxOptions = new FirefoxOptions();
            //         firefoxOptions.setProfile(new FirefoxProfile());
            //         driver = new FirefoxDriver(firefoxOptions);
            //         FirefoxProfile profile = new FirefoxProfile();
            //         profile.setPreference("browser.tabs.remote.autostart", false);
            //         profile.setPreference("browser.tabs.remote.autostart.1", false);
            //         profile.setPreference("browser.tabs.remote.autostart.2", false);
            //         profile.setPreference("browser.tabs.remote.force-enable", false);
            //         capability.setCapability(FirefoxDriver.PROFILE, profile);
            driver = new FirefoxDriver(capability);
        } else if (DRIVER_SAFARI.equals(curDriverStr)) {
            driver = new SafariDriver(capability);
        } else if (DRIVER_OPERA.equals(curDriverStr)) {
            driver = new OperaDriver(capability);
        } else if (DRIVER_PHANTOM_JS.equals(curDriverStr)) {
            driver = new PhantomJSDriver(capability);
        } else if (DRIVER_HTML_UNIT.equals(curDriverStr)) {
            driver = new HtmlUnitDriver(true);
        } else {
            throw new RuntimeException(String.format("Unknow type driver [%s].", curDriverStr));
        }

        if (timeout > 0) {
            driver.manage().timeouts().implicitlyWait(timeout, TimeUnit.SECONDS);
        }

        Window window = driver.manage().window();
        if (fullScreen) {
            try {
                //            window.fullscreen();
            } catch (UnsupportedCommandException e) {
                logger.error("Unsupported fullScreen command.", e);
            }
        }

        // ?cookie
        Options manage = driver.manage();
        boolean cookieLoad = Boolean.parseBoolean(enginePro.getProperty("cookie.load", "false"));
        File root = PathUtil.getRootDir();
        File cookieFile = new File(root, enginePro.getProperty("cookie.save.path", "phoenix.autotest.cookie"));

        if (cookieLoad) {
            try (ObjectInputStream input = new ObjectInputStream(new FileInputStream(cookieFile))) {
                Object cookiesObj = input.readObject();
                if (cookiesObj != null && cookiesObj instanceof Set<?>) {
                    Set<Cookie> cookies = (Set<Cookie>) cookiesObj;
                    for (Cookie cookie : cookies) {
                        manage.addCookie(cookie);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

        if (maximize) {
            window.maximize();
        }

        if (getWidth() > 0) {
            window.setSize(new Dimension(getWidth(), window.getSize().getHeight()));
        }

        if (getHeight() > 0) {
            window.setSize(new Dimension(window.getSize().getWidth(), getHeight()));
        }
    }

    /**
     * @return ??
     */
    public Map<Object, Object> getEngineConfig() {
        return Collections.unmodifiableMap(enginePro == null ? new Properties() : enginePro);
    }

    public void setProgressId(String key, String identify) {
        enginePro.put(key, identify);
    }

    /**
     * @return ?
     */
    public String getChromeVer() {
        return enginePro.getProperty(DriverConstants.DRIVER_CHROME + ".version");
    }

    public void setChromeVer(String ver) {
        enginePro.setProperty(DriverConstants.DRIVER_CHROME + ".version", ver);
    }

    /**
     * engine
     * @param enginePro
     * @throws MalformedURLException 
     */
    private void loadDefaultEnginePath(ClassLoader classLoader, Properties enginePro) throws MalformedURLException {
        Enumeration<URL> resurceUrls = null;
        URL defaultResourceUrl = null;
        try {
            resurceUrls = classLoader.getResources(ENGINE_CONFIG_FILE_NAME);
            defaultResourceUrl = classLoader.getResource(ENGINE_CONFIG_FILE_NAME);
        } catch (IOException e) {
            logger.error("Engine properties loading error.", e);
        }

        if (resurceUrls == null) {
            return;
        }

        //?jar
        while (resurceUrls.hasMoreElements()) {
            URL url = resurceUrls.nextElement();

            try {
                loadFromURL(enginePro, url);
            } catch (IOException e) {
                logger.error("loading engine error.", e);
            }
        }

        try {
            //?
            loadFromURL(enginePro, defaultResourceUrl);
        } catch (IOException e) {
            logger.error("loading engine error.", e);
        }

        loadDriverFromMapping(classLoader, enginePro);
    }

    /**
     * ?????
     * @param classLoader
     * @param enginePro
     * @throws MalformedURLException 
     */
    private void loadDriverFromMapping(ClassLoader classLoader, Properties enginePro) throws MalformedURLException {
        //?
        final String os = System.getProperty("os.name");
        final String arch = System.getProperty("os.arch");
        final String curDriverStr = getDriverStr();

        String commonOs = enginePro.getProperty("os.map.name." + os);
        String commonArch = enginePro.getProperty("os.map.arch." + arch);

        if (StringUtils.isAnyBlank(commonOs, commonArch)) {
            throw new RuntimeException(String.format("unknow os [%s] and arch [%s].", os, arch));
        }

        final String ver = enginePro.getProperty(curDriverStr + ".version");

        DriverMapping driverMapping = new DriverMapping();
        driverMapping.init();

        URL driverURL = null;
        String remoteDriverUrl = driverMapping.getUrl(curDriverStr, ver, commonOs, commonArch);
        if (remoteDriverUrl == null) {
            logger.error(String.format(
                    "Can not found remote driver url, browser is"
                            + " [%s], version is [%s], os is [%s], arch is [%s].",
                    curDriverStr, ver, commonOs, commonArch));
        } else {
            driverURL = new URL(remoteDriverUrl);

            String driverPath = null;
            try {
                driverPath = new DriverDownloader().getLocalFilePath(driverURL);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (StringUtils.isBlank(driverPath)) {
                throw new RuntimeException("Driver path is empty!");
            }

            enginePro.put(String.format("webdriver.%s.driver", curDriverStr), driverPath);
        }
    }

    private void loadFromURL(Properties enginePro, URL url) throws IOException {
        try (InputStream inputStream = url.openStream()) {
            enginePro.load(inputStream);
        }
    }

    /**
     * @return
     */
    public boolean storePro() {
        ClassLoader classLoader = this.getClass().getClassLoader();

        return storePro(classLoader);
    }

    /**
     * @param classLoader
     * @return
     */
    public boolean storePro(ClassLoader classLoader) {
        URL defaultResourceUrl = classLoader.getResource(ENGINE_CONFIG_FILE_NAME);
        try (OutputStream out = new FileOutputStream(
                new File(URLDecoder.decode(defaultResourceUrl.getFile(), "utf-8")))) {
            enginePro.store(out, "");

            return true;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return false;
    }

    /**
     * ?
     * @param driver
     * @return
     */
    public WebDriver turnToRootDriver(WebDriver driver) {
        return driver.switchTo().defaultContent();
    }

    /**
     * ?
     * @param url
     */
    public void openUrl(String url) {
        driver.get(url);

        dataMap.put("sys.startUrl", url);
    }

    /**
     * @return ????
     */
    public Map<String, Object> getDataMap() {
        return Collections.unmodifiableMap(dataMap);
    }

    /**
     * 
     * @param timeout ??
     */
    public void delayClose(long timeout) {
        ThreadUtil.silentSleep(timeout);

        close();
    }

    /**
     * ?
     */
    public void close() {
        if (driver != null) {
            Options manage = driver.manage();
            boolean cookieSave = Boolean.parseBoolean(enginePro.getProperty("cookie.save", "false"));
            File root = PathUtil.getRootDir();
            File cookieFile = new File(root, enginePro.getProperty("cookie.save.path", "phoenix.autotest.cookie"));

            if (cookieSave) {
                Set<Cookie> cookies = manage.getCookies();
                try (ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(cookieFile))) {
                    output.writeObject(cookies);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            driver.quit();
        }
    }

    /**
     * @return 
     */
    public WebDriver getDriver() {
        return driver;
    }

    /**
     * @return ??
     */
    public String getDriverStr() {
        return driverStr;
    }

    /**
     * ??
     * @param driverStr
     */
    public void setDriverStr(String driverStr) {
        this.driverStr = driverStr;
    }

    public String getRemoteStr() {
        return remoteStr;
    }

    public void setRemoteStr(String remoteStr) {
        this.remoteStr = remoteStr;
        if (remoteStr == null) {
            return;
        }

        for (DynamicData dynamicData : dynamicDataList) {
            if ("system".equals(dynamicData.getType())) {
                this.remoteStr = dynamicData.getValue(remoteStr);
                break;
            }
        }
    }

    /**
     * @return 
     */
    public long getTimeout() {
        return timeout;
    }

    /**
     * 
     * @param timeout
     */
    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

    /**
     * @return ?true?false
     */
    public boolean isFullScreen() {
        return fullScreen;
    }

    /**
     * ???
     * @param fullScreen
     */
    public void setFullScreen(boolean fullScreen) {
        this.fullScreen = fullScreen;
    }

    /**
     * @return ?
     */
    public int getWidth() {
        return width;
    }

    /**
     * ?
     * @param width
     */
    public void setWidth(int width) {
        this.width = width;
    }

    /**
     * @return ?
     */
    public int getHeight() {
        return height;
    }

    /**
     * ?
     * @param height
     */
    public void setHeight(int height) {
        this.height = height;
    }

    /**
     * @return the maximize
     */
    public boolean isMaximize() {
        return maximize;
    }

    /**
     * @param maximize the maximize to set
     */
    public void setMaximize(boolean maximize) {
        this.maximize = maximize;
    }

    /**
     * ?
     * @return
     */
    public int computeToolbarHeight() {
        JavascriptExecutor jsExe = (JavascriptExecutor) driver;
        Object objectHeight = jsExe.executeScript("return window.outerHeight - window.innerHeight;");
        if (objectHeight instanceof Long) {
            toolbarHeight = ((Long) objectHeight).intValue();
        }

        return toolbarHeight;
    }

    /**
     * @return the toolbarHeight
     */
    public int getToolbarHeight() {
        return toolbarHeight;
    }
}