io.github.bonigarcia.wdm.WebDriverManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of webdrivermanager Show documentation
Show all versions of webdrivermanager Show documentation
Automated driver management and other helper features for Selenium
WebDriver in Java
/*
* (C) Copyright 2015 Boni Garcia (http://bonigarcia.github.io/)
*
* 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 io.github.bonigarcia.wdm;
import static io.github.bonigarcia.wdm.Architecture.X32;
import static io.github.bonigarcia.wdm.Architecture.X64;
import static io.github.bonigarcia.wdm.Config.isNullOrEmpty;
import static io.github.bonigarcia.wdm.DriverManagerType.CHROME;
import static io.github.bonigarcia.wdm.DriverManagerType.EDGE;
import static io.github.bonigarcia.wdm.DriverManagerType.FIREFOX;
import static io.github.bonigarcia.wdm.DriverManagerType.IEXPLORER;
import static io.github.bonigarcia.wdm.DriverManagerType.OPERA;
import static io.github.bonigarcia.wdm.DriverManagerType.PHANTOMJS;
import static io.github.bonigarcia.wdm.DriverManagerType.SELENIUM_SERVER_STANDALONE;
import static io.github.bonigarcia.wdm.OperatingSystem.WIN;
import static io.github.bonigarcia.wdm.Shell.getVersionFromPosixOutput;
import static io.github.bonigarcia.wdm.Shell.getVersionFromWmicOutput;
import static io.github.bonigarcia.wdm.Shell.runAndWait;
import static java.lang.Integer.parseInt;
import static java.lang.Integer.signum;
import static java.lang.Integer.valueOf;
import static java.lang.invoke.MethodHandles.lookup;
import static java.util.Collections.sort;
import static java.util.Optional.empty;
import static javax.xml.xpath.XPathConstants.NODESET;
import static javax.xml.xpath.XPathFactory.newInstance;
import static org.apache.commons.io.FileUtils.deleteDirectory;
import static org.apache.commons.io.FileUtils.listFiles;
import static org.apache.commons.io.FilenameUtils.removeExtension;
import static org.apache.commons.lang3.StringUtils.isNumeric;
import static org.apache.commons.lang3.SystemUtils.IS_OS_LINUX;
import static org.apache.commons.lang3.SystemUtils.IS_OS_MAC;
import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS;
import static org.slf4j.LoggerFactory.getLogger;
import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.jsoup.Jsoup;
import org.slf4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.internal.LinkedTreeMap;
/**
* Parent driver manager.
*
* @author Boni Garcia ([email protected])
* @since 2.1.0
*/
public abstract class WebDriverManager {
static final Logger log = getLogger(lookup().lookupClass());
protected static final String SLASH = "/";
protected static final String PRE_INSTALLED = "pre-installed";
protected static final String BETA = "beta";
protected static final String ONLINE = "online";
protected static final String LOCAL = "local";
protected abstract List getDrivers() throws IOException;
protected abstract Optional getBrowserVersion();
protected abstract DriverManagerType getDriverManagerType();
protected abstract String getDriverName();
protected abstract void setDriverVersion(String version);
protected abstract String getDriverVersion();
protected abstract void setDriverUrl(URL url);
protected abstract URL getDriverUrl();
protected abstract Optional getMirrorUrl();
protected abstract Optional getExportParameter();
protected static Map instanceMap = new EnumMap<>(
DriverManagerType.class);
protected HttpClient httpClient;
protected Downloader downloader;
protected UrlFilter urlFilter;
protected String versionToDownload;
protected String downloadedVersion;
protected String latestVersion;
protected String binaryPath;
protected boolean mirrorLog;
protected List listVersions;
protected boolean forcedArch;
protected boolean forcedOs;
protected boolean isLatest;
protected boolean retry = true;
protected Config config = new Config();
protected Preferences preferences = new Preferences(config);
protected String preferenceKey;
protected Properties versionsProperties;
public static Config globalConfig() {
Config global = new Config();
global.setAvoidAutoReset(true);
for (DriverManagerType type : DriverManagerType.values()) {
WebDriverManager.getInstance(type).setConfig(global);
}
return global;
}
public Config config() {
return config;
}
public static synchronized WebDriverManager chromedriver() {
if (!instanceMap.containsKey(CHROME)) {
instanceMap.put(CHROME, new ChromeDriverManager());
}
return instanceMap.get(CHROME);
}
public static synchronized WebDriverManager firefoxdriver() {
if (!instanceMap.containsKey(FIREFOX)) {
instanceMap.put(FIREFOX, new FirefoxDriverManager());
}
return instanceMap.get(FIREFOX);
}
public static synchronized WebDriverManager operadriver() {
if (!instanceMap.containsKey(OPERA)) {
instanceMap.put(OPERA, new OperaDriverManager());
}
return instanceMap.get(OPERA);
}
public static synchronized WebDriverManager edgedriver() {
if (!instanceMap.containsKey(EDGE)) {
instanceMap.put(EDGE, new EdgeDriverManager());
}
return instanceMap.get(EDGE);
}
public static synchronized WebDriverManager iedriver() {
if (!instanceMap.containsKey(IEXPLORER)) {
instanceMap.put(IEXPLORER, new InternetExplorerDriverManager());
}
return instanceMap.get(IEXPLORER);
}
public static synchronized WebDriverManager phantomjs() {
if (!instanceMap.containsKey(PHANTOMJS)) {
instanceMap.put(PHANTOMJS, new PhantomJsDriverManager());
}
return instanceMap.get(PHANTOMJS);
}
public static synchronized WebDriverManager seleniumServerStandalone() {
if (!instanceMap.containsKey(SELENIUM_SERVER_STANDALONE)) {
instanceMap.put(SELENIUM_SERVER_STANDALONE,
new SeleniumServerStandaloneManager());
}
return instanceMap.get(SELENIUM_SERVER_STANDALONE);
}
protected static synchronized WebDriverManager voiddriver() {
return new VoidDriverManager();
}
public static synchronized WebDriverManager getInstance(
DriverManagerType driverManagerType) {
if (driverManagerType == null) {
return voiddriver();
}
switch (driverManagerType) {
case CHROME:
return chromedriver();
case FIREFOX:
return firefoxdriver();
case OPERA:
return operadriver();
case IEXPLORER:
return iedriver();
case EDGE:
return edgedriver();
case PHANTOMJS:
return phantomjs();
case SELENIUM_SERVER_STANDALONE:
return seleniumServerStandalone();
default:
return voiddriver();
}
}
public static synchronized WebDriverManager getInstance(
Class> webDriverClass) {
switch (webDriverClass.getName()) {
case "org.openqa.selenium.chrome.ChromeDriver":
return chromedriver();
case "org.openqa.selenium.firefox.FirefoxDriver":
return firefoxdriver();
case "org.openqa.selenium.opera.OperaDriver":
return operadriver();
case "org.openqa.selenium.ie.InternetExplorerDriver":
return iedriver();
case "org.openqa.selenium.edge.EdgeDriver":
return edgedriver();
case "org.openqa.selenium.phantomjs.PhantomJSDriver":
return phantomjs();
default:
return voiddriver();
}
}
public synchronized void setup() {
if (getDriverManagerType() != null) {
try {
Architecture architecture = config().getArchitecture();
String driverVersion = getDriverVersion();
isLatest = isVersionLatest(driverVersion);
manage(architecture, driverVersion);
} finally {
if (!config().isAvoidAutoReset()) {
reset();
}
}
}
}
public WebDriverManager version(String version) {
setDriverVersion(version);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager architecture(Architecture architecture) {
config().setArchitecture(architecture);
forcedArch = true;
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager arch32() {
architecture(X32);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager arch64() {
architecture(X64);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager operatingSystem(OperatingSystem os) {
config().setOs(os.name());
forcedOs = true;
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager forceCache() {
config().setForceCache(true);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager forceDownload() {
config().setOverride(true);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager driverRepositoryUrl(URL url) {
setDriverUrl(url);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager useMirror() {
Optional mirrorUrl = getMirrorUrl();
if (!mirrorUrl.isPresent()) {
throw new WebDriverManagerException("Mirror URL not available");
}
config().setUseMirror(true);
setDriverUrl(mirrorUrl.get());
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager proxy(String proxy) {
config().setProxy(proxy);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager proxyUser(String proxyUser) {
config().setProxyUser(proxyUser);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager proxyPass(String proxyPass) {
config().setProxyPass(proxyPass);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager useBetaVersions() {
config().setUseBetaVersions(true);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager ignoreVersions(String... versions) {
config().setIgnoreVersions(versions);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager gitHubTokenName(String gitHubTokenName) {
config().setGitHubTokenName(gitHubTokenName);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager gitHubTokenSecret(String gitHubTokenSecret) {
config().setGitHubTokenSecret(gitHubTokenSecret);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager timeout(int timeout) {
config().setTimeout(timeout);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager properties(String properties) {
config().setProperties(properties);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager targetPath(String targetPath) {
config().setTargetPath(targetPath);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager avoidExport() {
config().setAvoidExport(true);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager avoidOutputTree() {
config().setAvoidOutputTree(true);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager avoidAutoVersion() {
config().setAvoidAutoVersion(true);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager avoidPreferences() {
config().setAvoidPreferences(true);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager ttl(int seconds) {
config().setTtl(seconds);
return instanceMap.get(getDriverManagerType());
}
public WebDriverManager browserPath(String browserPath) {
config().setBinaryPath(browserPath);
return instanceMap.get(getDriverManagerType());
}
// ------------
public String getBinaryPath() {
return instanceMap.get(getDriverManagerType()).binaryPath;
}
public String getDownloadedVersion() {
return instanceMap.get(getDriverManagerType()).downloadedVersion;
}
public List getVersions() {
httpClient = new HttpClient(config());
try {
List drivers = getDrivers();
List versions = new ArrayList<>();
for (URL url : drivers) {
String version = getCurrentVersion(url, getDriverName());
if (version.isEmpty() || version.equalsIgnoreCase("icons")) {
continue;
}
if (version.startsWith(".")) {
version = version.substring(1);
}
if (!versions.contains(version)) {
versions.add(version);
}
}
log.trace("Version list before sorting {}", versions);
sort(versions, new VersionComparator());
return versions;
} catch (IOException e) {
throw new WebDriverManagerException(e);
}
}
public void clearPreferences() {
instanceMap.get(getDriverManagerType()).preferences.clear();
}
public void clearCache() {
String targetPath = config().getTargetPath();
try {
log.debug("Clearing cache at {}", targetPath);
deleteDirectory(new File(targetPath));
} catch (Exception e) {
log.warn("Exception deleting cache at {}", targetPath, e);
}
}
// ------------
protected String preDownload(String target, String version) {
log.trace("Pre-download. target={}, version={}", target, version);
return target;
}
protected File postDownload(File archive) {
File parentFolder = archive.getParentFile();
File[] ls = parentFolder.listFiles();
for (File f : ls) {
if (getDriverName().contains(removeExtension(f.getName()))) {
log.trace("Found binary in post-download: {}", f);
return f;
}
}
throw new WebDriverManagerException("Driver " + getDriverName()
+ " not found (using temporal folder " + parentFolder + ")");
}
protected String getCurrentVersion(URL url, String driverName) {
String currentVersion = "";
try {
currentVersion = url.getFile().substring(
url.getFile().indexOf(SLASH) + 1,
url.getFile().lastIndexOf(SLASH));
} catch (StringIndexOutOfBoundsException e) {
log.trace("Exception getting version of URL {} ({})", url,
e.getMessage());
}
return currentVersion;
}
protected void manage(Architecture arch, String version) {
httpClient = new HttpClient(config());
try (HttpClient wdmHttpClient = httpClient) {
downloader = new Downloader(getDriverManagerType());
urlFilter = new UrlFilter();
boolean getLatest = isVersionLatest(version);
boolean cache = config().isForceCache();
if (getLatest) {
version = detectDriverVersionFromBrowser();
}
getLatest = isNullOrEmpty(version);
// Check latest version
if (getLatest && !config().isUseBetaVersions()) {
Optional lastVersion = getLatestVersion();
getLatest = !lastVersion.isPresent();
if (!getLatest) {
version = lastVersion.get();
}
}
// For Edge
if (checkPreInstalledVersion(version)) {
return;
}
String os = config().getOs();
log.trace("Managing {} arch={} version={} getLatest={} cache={}",
getDriverName(), arch, version, getLatest, cache);
if (getLatest && latestVersion != null) {
log.debug("Latest version of {} is {} (recently resolved)",
getDriverName(), latestVersion);
version = latestVersion;
cache = true;
}
Optional driverInCache = handleCache(arch, version, os,
getLatest, cache);
String versionStr = getLatest ? "(latest version)" : version;
if (driverInCache.isPresent() && !config().isOverride()) {
storeVersionToDownload(version);
downloadedVersion = version;
log.debug("Driver {} {} found in cache", getDriverName(),
versionStr);
exportDriver(driverInCache.get());
} else {
List candidateUrls = filterCandidateUrls(arch, version,
getLatest);
if (candidateUrls.isEmpty()) {
String errorMessage = getDriverName() + " " + versionStr
+ " for " + os + arch.toString() + " not found in "
+ getDriverUrl();
log.error(errorMessage);
throw new WebDriverManagerException(errorMessage);
}
downloadCandidateUrls(candidateUrls);
}
} catch (Exception e) {
handleException(e, arch, version);
}
}
private String detectDriverVersionFromBrowser() {
String version = "";
if (config().isAvoidAutoVersion()) {
return version;
}
Optional optionalBrowserVersion = getBrowserVersion();
if (optionalBrowserVersion.isPresent()) {
String browserVersion = optionalBrowserVersion.get();
log.trace("Detected {} version {}", getDriverManagerType(),
browserVersion);
preferenceKey = getDriverManagerType().name().toLowerCase()
+ browserVersion;
if (usePreferences()
&& preferences.checkKeyInPreferences(preferenceKey)) {
// Get driver version from preferences
version = preferences.getValueFromPreferences(preferenceKey);
} else {
// Get driver version from properties
version = getVersionForInstalledBrowser(browserVersion);
}
if (!isNullOrEmpty(version)) {
log.info(
"Using {} {} (since {} {} is installed in your machine)",
getDriverName(), version, getDriverManagerType(),
browserVersion);
}
} else {
log.debug(
"The proper {} version for your {} is unknown ... trying with the latest",
getDriverName(), getDriverManagerType());
}
return version;
}
private boolean usePreferences() {
boolean usePrefs = !config().isAvoidPreferences()
&& !config().isOverride() && !forcedArch && !forcedOs;
log.trace("Using preferences {}", usePrefs);
return usePrefs;
}
private boolean checkPreInstalledVersion(String version) {
if (version.equals(PRE_INSTALLED)) {
String systemRoot = System.getenv("SystemRoot");
File microsoftWebDriverFile = new File(systemRoot,
"System32" + File.separator + "MicrosoftWebDriver.exe");
if (microsoftWebDriverFile.exists()) {
downloadedVersion = PRE_INSTALLED;
exportDriver(microsoftWebDriverFile.toString());
return true;
} else {
retry = false;
throw new WebDriverManagerException(
"MicrosoftWebDriver.exe should be pre-installed in an elevated command prompt executing: "
+ "dism /Online /Add-Capability /CapabilityName:Microsoft.WebDriver~~~~0.0.1.0");
}
}
return false;
}
private boolean isVersionLatest(String version) {
return isNullOrEmpty(version) || version.equalsIgnoreCase("latest");
}
private String getVersionForInstalledBrowser(String browserVersion) {
String driverVersion = "";
DriverManagerType driverManagerType = getDriverManagerType();
String driverLowerCase = driverManagerType.name().toLowerCase();
Optional driverVersionForBrowser = getDriverVersionForBrowserFromProperties(
driverLowerCase + browserVersion, false);
if (driverVersionForBrowser.isPresent()) {
driverVersion = driverVersionForBrowser.get();
} else {
log.debug(
"The driver version for {} {} is unknown ... trying with latest",
driverManagerType, browserVersion);
}
return driverVersion;
}
private Optional getDriverVersionForBrowserFromProperties(
String key, boolean online) {
String onlineMessage = online ? ONLINE : LOCAL;
log.trace("Getting driver version from {} properties for {}",
onlineMessage, key);
String value = getVersionFromProperties(online).getProperty(key);
if (value == null) {
log.debug("Driver for {} not found in {} properties", key,
onlineMessage);
versionsProperties = null;
value = getVersionFromProperties(!online).getProperty(key);
}
return value == null ? empty() : Optional.of(value);
}
private Properties getVersionFromProperties(boolean online) {
if (versionsProperties != null) {
log.trace("Already created versions.properties");
return versionsProperties;
} else {
try {
InputStream inputStream = getVersionsInputStream(online);
versionsProperties = new Properties();
versionsProperties.load(inputStream);
inputStream.close();
} catch (Exception e) {
versionsProperties = null;
throw new IllegalStateException(
"Cannot read versions.properties", e);
}
return versionsProperties;
}
}
private InputStream getVersionsInputStream(boolean online)
throws IOException {
String onlineMessage = online ? ONLINE : LOCAL;
log.trace("Reading {} version.properties to find out driver version",
onlineMessage);
InputStream inputStream;
try {
if (online) {
inputStream = getOnlineVersionsInputStream();
} else {
inputStream = getLocalVersionsInputStream();
}
} catch (Exception e) {
String exceptionMessage = online ? LOCAL : ONLINE;
log.warn("Error reading version.properties, using {} instead",
exceptionMessage);
if (online) {
inputStream = getLocalVersionsInputStream();
} else {
inputStream = getOnlineVersionsInputStream();
}
}
return inputStream;
}
private InputStream getLocalVersionsInputStream() {
InputStream inputStream;
inputStream = Config.class.getResourceAsStream("/versions.properties");
return inputStream;
}
private InputStream getOnlineVersionsInputStream() throws IOException {
return httpClient
.execute(httpClient
.createHttpGet(config().getVersionsPropertiesUrl()))
.getEntity().getContent();
}
protected void handleException(Exception e, Architecture arch,
String version) {
String versionStr = isNullOrEmpty(version) ? "(latest version)"
: version;
String errorMessage = String.format(
"There was an error managing %s %s (%s)", getDriverName(),
versionStr, e.getMessage());
if (!config().isForceCache() && retry) {
config().setForceCache(true);
config().setUseMirror(true);
retry = false;
log.warn("{} ... trying again using cache and mirror",
errorMessage);
manage(arch, version);
} else {
log.error("{}", errorMessage, e);
throw new WebDriverManagerException(e);
}
}
protected void downloadCandidateUrls(List candidateUrls)
throws IOException, InterruptedException {
URL url = candidateUrls.iterator().next();
String exportValue = downloader.download(url, versionToDownload,
getDriverName());
exportDriver(exportValue);
downloadedVersion = versionToDownload;
}
protected List filterCandidateUrls(Architecture arch, String version,
boolean getLatest) throws IOException {
List urls = getDrivers();
List candidateUrls;
log.trace("All URLs: {}", urls);
boolean continueSearchingVersion;
do {
// Get the latest or concrete version
candidateUrls = getLatest ? checkLatest(urls, getDriverName())
: getVersion(urls, getDriverName(), version);
log.trace("Candidate URLs: {}", candidateUrls);
if (versionToDownload == null
|| this.getClass().equals(EdgeDriverManager.class)) {
break;
}
// Filter by OS
if (!getDriverName().equalsIgnoreCase("IEDriverServer")
&& !getDriverName()
.equalsIgnoreCase("selenium-server-standalone")) {
candidateUrls = urlFilter.filterByOs(candidateUrls,
config().getOs());
}
// Filter by architecture
candidateUrls = urlFilter.filterByArch(candidateUrls, arch,
forcedArch);
// Filter by distro
candidateUrls = filterByDistro(candidateUrls);
// Filter by ignored versions
candidateUrls = filterByIgnoredVersions(candidateUrls);
// Find out if driver version has been found or not
continueSearchingVersion = candidateUrls.isEmpty() && getLatest;
if (continueSearchingVersion) {
log.info(
"No binary found for {} {} ... seeking another version",
getDriverName(), versionToDownload);
urls = removeFromList(urls, versionToDownload);
versionToDownload = null;
}
} while (continueSearchingVersion);
return candidateUrls;
}
protected List filterByIgnoredVersions(List candidateUrls) {
if (config().getIgnoreVersions() != null && !candidateUrls.isEmpty()) {
candidateUrls = urlFilter.filterByIgnoredVersions(candidateUrls,
config().getIgnoreVersions());
}
return candidateUrls;
}
protected List filterByDistro(List candidateUrls)
throws IOException {
// Filter phantomjs 2.5.0 in Linux
if (config().getOs().equalsIgnoreCase("linux")
&& getDriverName().contains("phantomjs")) {
candidateUrls = urlFilter.filterByDistro(candidateUrls, "2.5.0");
}
return candidateUrls;
}
protected Optional handleCache(Architecture arch, String version,
String os, boolean getLatest, boolean cache) {
Optional driverInCache = empty();
if (cache || !getLatest) {
driverInCache = getDriverFromCache(version, arch, os);
}
storeVersionToDownload(version);
return driverInCache;
}
protected Optional getDriverFromCache(String driverVersion,
Architecture arch, String os) {
log.trace("Checking if {} exists in cache", getDriverName());
List filesInCache = getFilesInCache();
if (!filesInCache.isEmpty()) {
// Filter by name
filesInCache = filterCacheBy(filesInCache, getDriverName());
// Filter by version
filesInCache = filterCacheBy(filesInCache, driverVersion);
// Filter by OS
if (!getDriverName().equals("msedgedriver")) {
filesInCache = filterCacheBy(filesInCache, os.toLowerCase());
}
if (filesInCache.size() == 1) {
return Optional.of(filesInCache.get(0).toString());
}
// Filter by arch
filesInCache = filterCacheBy(filesInCache, arch.toString());
if (!filesInCache.isEmpty()) {
return Optional.of(
filesInCache.get(filesInCache.size() - 1).toString());
}
}
log.trace("{} not found in cache", getDriverName());
return empty();
}
protected List filterCacheBy(List input, String key) {
List output = new ArrayList<>(input);
if (!key.isEmpty() && !input.isEmpty()) {
for (File f : input) {
if (!f.toString().contains(key)) {
output.remove(f);
}
}
}
log.trace("Filter cache by {} -- input list {} -- output list {} ", key,
input, output);
return output;
}
protected List getFilesInCache() {
return (List) listFiles(new File(downloader.getTargetPath()),
null, true);
}
protected List removeFromList(List list, String version) {
List out = new ArrayList<>(list);
for (URL url : list) {
if (url.getFile().contains(version)) {
out.remove(url);
}
}
return out;
}
protected List getVersion(List list, String driver,
String version) {
List out = new ArrayList<>();
if (getDriverName().contains("msedgedriver")) {
int i = listVersions.indexOf(version);
if (i != -1) {
out.add(list.get(i));
}
}
for (URL url : list) {
if (url.getFile().contains(driver)
&& url.getFile().contains(version)
&& !url.getFile().contains("-symbols")) {
out.add(url);
}
}
if (versionToDownload != null && !versionToDownload.equals(version)) {
versionToDownload = version;
log.info("Using {} {}", driver, version);
}
return out;
}
protected List checkLatest(List list, String driver) {
log.trace("Checking the lastest version of {} with URL list {}", driver,
list);
List out = new ArrayList<>();
List copyOfList = new ArrayList<>(list);
for (URL url : copyOfList) {
try {
handleDriver(url, driver, out);
} catch (Exception e) {
log.trace("There was a problem with URL {} : {}", url,
e.getMessage());
list.remove(url);
}
}
storeVersionToDownload(versionToDownload);
latestVersion = versionToDownload;
log.info("Latest version of {} is {}", driver, versionToDownload);
return out;
}
protected void handleDriver(URL url, String driver, List out) {
if (!config().isUseBetaVersions()
&& (url.getFile().toLowerCase().contains("beta"))) {
return;
}
if (url.getFile().contains(driver)) {
String currentVersion = getCurrentVersion(url, driver);
if (currentVersion.equalsIgnoreCase(driver)) {
return;
}
if (versionToDownload == null) {
versionToDownload = currentVersion;
}
if (versionCompare(currentVersion, versionToDownload) > 0) {
versionToDownload = currentVersion;
out.clear();
}
if (url.getFile().contains(versionToDownload)) {
out.add(url);
}
}
}
protected boolean isUsingTaobaoMirror() {
return getDriverUrl().getHost().equalsIgnoreCase("npm.taobao.org");
}
protected Integer versionCompare(String str1, String str2) {
String[] vals1 = str1.replaceAll("v", "").split("\\.");
String[] vals2 = str2.replaceAll("v", "").split("\\.");
if (vals1[0].equals("")) {
vals1[0] = "0";
}
if (vals2[0].equals("")) {
vals2[0] = "0";
}
int i = 0;
while (i < vals1.length && i < vals2.length
&& vals1[i].equals(vals2[i])) {
i++;
}
if (i < vals1.length && i < vals2.length) {
return signum(valueOf(vals1[i]).compareTo(valueOf(vals2[i])));
} else {
return signum(vals1.length - vals2.length);
}
}
/**
* This method works also for http://npm.taobao.org/ and
* https://bitbucket.org/ mirrors.
*/
protected List getDriversFromMirror(URL driverUrl) throws IOException {
if (mirrorLog) {
log.info("Crawling driver list from mirror {}", driverUrl);
mirrorLog = true;
} else {
log.trace("[Recursive call] Crawling driver list from mirror {}",
driverUrl);
}
String driverStr = driverUrl.toString();
String driverUrlContent = driverUrl.getPath();
HttpResponse response = httpClient
.execute(httpClient.createHttpGet(driverUrl));
try (InputStream in = response.getEntity().getContent()) {
org.jsoup.nodes.Document doc = Jsoup.parse(in, null, "");
Iterator iterator = doc.select("a")
.iterator();
List urlList = new ArrayList<>();
while (iterator.hasNext()) {
String link = iterator.next().attr("href");
if (link.contains("mirror") && link.endsWith(SLASH)) {
urlList.addAll(getDriversFromMirror(new URL(
driverStr + link.replace(driverUrlContent, ""))));
} else if (link.startsWith(driverUrlContent)
&& !link.contains("icons")) {
urlList.add(new URL(
driverStr + link.replace(driverUrlContent, "")));
}
}
return urlList;
}
}
protected List getDriversFromXml(URL driverUrl) throws IOException {
log.info("Reading {} to seek {}", driverUrl, getDriverName());
List urls = new ArrayList<>();
HttpResponse response = httpClient
.execute(httpClient.createHttpGet(driverUrl));
try {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()))) {
Document xml = loadXML(reader);
NodeList nodes = (NodeList) newInstance().newXPath().evaluate(
"//Contents/Key", xml.getDocumentElement(), NODESET);
for (int i = 0; i < nodes.getLength(); ++i) {
Element e = (Element) nodes.item(i);
urls.add(new URL(driverUrl.toURI().resolve(".")
+ e.getChildNodes().item(0).getNodeValue()));
}
}
} catch (Exception e) {
throw new WebDriverManagerException(e);
}
return urls;
}
protected Document loadXML(Reader reader)
throws SAXException, IOException, ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(reader);
return builder.parse(is);
}
protected void exportDriver(String variableValue) {
binaryPath = variableValue;
Optional exportParameter = getExportParameter();
if (!config.isAvoidExport() && exportParameter.isPresent()) {
String variableName = exportParameter.get();
log.info("Exporting {} as {}", variableName, variableValue);
System.setProperty(variableName, variableValue);
} else {
log.info("Resulting binary {}", variableValue);
}
}
protected InputStream openGitHubConnection(URL driverUrl)
throws IOException {
HttpGet get = httpClient.createHttpGet(driverUrl);
String gitHubTokenName = config().getGitHubTokenName();
String gitHubTokenSecret = config().getGitHubTokenSecret();
if (!isNullOrEmpty(gitHubTokenName)
&& !isNullOrEmpty(gitHubTokenSecret)) {
String userpass = gitHubTokenName + ":" + gitHubTokenSecret;
String basicAuth = "Basic "
+ new String(new Base64().encode(userpass.getBytes()));
get.addHeader("Authorization", basicAuth);
}
return httpClient.execute(get).getEntity().getContent();
}
protected List getDriversFromGitHub() throws IOException {
List urls;
URL driverUrl = getDriverUrl();
log.info("Reading {} to seek {}", driverUrl, getDriverName());
if (isUsingTaobaoMirror()) {
urls = getDriversFromMirror(driverUrl);
} else {
String driverVersion = versionToDownload;
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(openGitHubConnection(driverUrl)))) {
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
GitHubApi[] releaseArray = gson.fromJson(reader,
GitHubApi[].class);
if (driverVersion != null) {
releaseArray = new GitHubApi[] {
getVersion(releaseArray, driverVersion) };
}
urls = new ArrayList<>();
for (GitHubApi release : releaseArray) {
if (release != null) {
List> assets = release
.getAssets();
for (LinkedTreeMap asset : assets) {
urls.add(new URL(asset.get("browser_download_url")
.toString()));
}
}
}
}
}
return urls;
}
protected GitHubApi getVersion(GitHubApi[] releaseArray, String version) {
GitHubApi out = null;
for (GitHubApi release : releaseArray) {
log.trace("Get version {} of {}", version, release);
if ((release.getName() != null
&& release.getName().contains(version))
|| (release.getTagName() != null
&& release.getTagName().contains(version))) {
out = release;
break;
}
}
return out;
}
protected HttpClient getHttpClient() {
return httpClient;
}
protected FilenameFilter getFolderFilter() {
return (dir, name) -> dir.isDirectory()
&& name.toLowerCase().contains(getDriverName());
}
protected Optional getDefaultBrowserVersion(String programFilesEnv,
String winBrowserName, String linuxBrowserName,
String macBrowserName, String versionFlag,
String browserNameInOutput) {
String browserBinaryPath = config().getBinaryPath();
if (IS_OS_WINDOWS) {
String programFiles = System.getenv(programFilesEnv)
.replaceAll("\\\\", "\\\\\\\\");
String browserPath = isNullOrEmpty(browserBinaryPath)
? programFiles + winBrowserName
: browserBinaryPath;
String browserVersionOutput = runAndWait(getExecFile(), "wmic",
"datafile", "where", "name='" + browserPath + "'", "get",
"Version", "/value");
if (!isNullOrEmpty(browserVersionOutput)) {
return Optional
.of(getVersionFromWmicOutput(browserVersionOutput));
}
} else if (IS_OS_LINUX || IS_OS_MAC) {
String browserPath;
if (!isNullOrEmpty(browserBinaryPath)) {
browserPath = browserBinaryPath;
} else {
browserPath = IS_OS_LINUX ? linuxBrowserName : macBrowserName;
}
String browserVersionOutput = runAndWait(browserPath, versionFlag);
if (!isNullOrEmpty(browserVersionOutput)) {
return Optional.of(getVersionFromPosixOutput(
browserVersionOutput, browserNameInOutput));
}
}
return empty();
}
protected File getExecFile() {
String systemRoot = System.getenv("SystemRoot");
File system32 = new File(systemRoot, "System32");
if (IS_OS_WINDOWS && system32.exists() && system32.isDirectory()) {
return system32;
}
return new File(".");
}
protected Optional getLatestVersion() {
return empty();
}
protected void reset() {
config().reset();
mirrorLog = false;
listVersions = null;
versionToDownload = null;
forcedArch = false;
forcedOs = false;
retry = true;
isLatest = true;
}
protected String getProgramFilesEnv() {
return System.getProperty("os.arch").contains("64")
? "PROGRAMFILES(X86)"
: "PROGRAMFILES";
}
protected URL getDriverUrlCkeckingMirror(URL url) {
if (config().isUseMirror()) {
Optional mirrorUrl = getMirrorUrl();
if (mirrorUrl.isPresent()) {
return mirrorUrl.get();
}
}
return url;
}
public static void main(String[] args) {
String validBrowsers = "chrome|firefox|opera|edge|phantomjs|iexplorer|selenium_server_standalone";
if (args.length <= 0) {
logCliError(validBrowsers);
} else {
String arg = args[0];
if (arg.equalsIgnoreCase("server")) {
startServer(args);
} else if (arg.equalsIgnoreCase("clear-preferences")) {
new Preferences(new Config()).clear();
} else {
resolveLocal(validBrowsers, arg);
}
}
}
private static void resolveLocal(String validBrowsers, String arg) {
log.info("Using WebDriverManager to resolve {}", arg);
try {
DriverManagerType driverManagerType = DriverManagerType
.valueOf(arg.toUpperCase());
WebDriverManager wdm = WebDriverManager
.getInstance(driverManagerType).avoidExport()
.targetPath(".").avoidAutoVersion().forceDownload();
if (arg.equalsIgnoreCase("edge")
|| arg.equalsIgnoreCase("iexplorer")) {
wdm.operatingSystem(WIN);
}
wdm.avoidOutputTree().setup();
} catch (Exception e) {
log.error("Driver for {} not found (valid browsers {})", arg,
validBrowsers);
}
}
private static void startServer(String[] args) {
int port = new Config().getServerPort();
if (args.length > 1 && isNumeric(args[1])) {
port = parseInt(args[1]);
}
new Server(port);
}
private static void logCliError(String validBrowsers) {
log.error("There are 3 options to run WebDriverManager CLI");
log.error(
"1. WebDriverManager used to resolve binary drivers locally:");
log.error("\tWebDriverManager browserName");
log.error("\t(where browserName={})", validBrowsers);
log.error("2. WebDriverManager as a server:");
log.error("\tWebDriverManager server ");
log.error("\t(where default port is 4041)");
log.error(
"3. To clear previously resolved driver versions (as Java preferences):");
log.error("\tWebDriverManager clear-preferences");
}
private void storeVersionToDownload(String version) {
if (!isNullOrEmpty(version)) {
if (version.startsWith(".")) {
version = version.substring(1);
}
versionToDownload = version;
if (isLatest && usePreferences() && !isNullOrEmpty(preferenceKey)) {
preferences.putValueInPreferencesIfEmpty(preferenceKey,
version);
}
}
}
private void setConfig(Config config) {
this.config = config;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy