001/*
002 * Copyright 2013 Atteo.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.atteo.moonshine.webdriver;
017
018import java.util.Locale;
019import java.util.concurrent.TimeUnit;
020
021import javax.xml.bind.annotation.XmlElement;
022import javax.xml.bind.annotation.XmlRootElement;
023
024import org.atteo.evo.classindex.ClassIndex;
025import org.atteo.evo.config.XmlDefaultValue;
026import org.atteo.moonshine.TopLevelService;
027import org.atteo.moonshine.webdriver.browsers.Browser;
028import org.openqa.selenium.remote.RemoteWebDriver;
029
030import com.google.inject.AbstractModule;
031import com.google.inject.Module;
032
033/**
034 * Starts the browser and binds the {@link RemoteWebDriver} which can be used to drive it.
035 */
036@XmlRootElement(name = "webdriver")
037public class WebDriverService extends TopLevelService {
038    private static final Iterable<Class<? extends Browser>> browsers = ClassIndex.getSubclasses(Browser.class);
039
040    /**
041     * Browser which should be started.
042     */
043    @XmlElement(name = "browser")
044    @XmlDefaultValue("${oneof:${browser},chrome}")
045    private String browserName;
046
047    /**
048     * Implicit wait time in seconds.
049     * @see WebDriver.Timeouts#implicitlyWait
050     */
051    @XmlElement
052    private long timeoutInSeconds = 2;
053
054    private Browser browser;
055    private RemoteWebDriver driver;
056
057    @Override
058    public Module configure() {
059        return new AbstractModule() {
060            @Override
061            protected void configure() {
062                browser = getSelectedBrowser();
063                driver = browser.createDriver();
064                driver.manage().timeouts().implicitlyWait(timeoutInSeconds, TimeUnit.SECONDS);
065                bind(RemoteWebDriver.class).toInstance(driver);
066            }
067        };
068    }
069
070    private Browser getSelectedBrowser() {
071        for (Class<? extends Browser> browserClass : browsers) {
072            String name = browserClass.getSimpleName().toLowerCase(Locale.ENGLISH);
073            if (name.endsWith("browser")) {
074                name = name.substring(0, name.length() - "browser".length());
075            }
076            if (name.equals(browserName)) {
077                try {
078                    return browserClass.newInstance();
079                } catch (InstantiationException| IllegalAccessException e) {
080                    throw new RuntimeException(e);
081                }
082            }
083        }
084        throw new RuntimeException("Selected browser not found: '" + browserName + "'");
085    }
086
087    @Override
088    public void close() {
089        if (driver != null) {
090            driver.close();
091        }
092        if (browser != null) {
093            browser.close();
094        }
095    }
096}