io.github.bonigarcia.wdm.Downloader Maven / Gradle / Ivy
/*
* (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.Config.listToString;
import static io.github.bonigarcia.wdm.WebDriverManager.config;
import static java.io.File.separator;
import static java.lang.Runtime.getRuntime;
import static java.lang.invoke.MethodHandles.lookup;
import static java.nio.file.Files.createTempDirectory;
import static java.nio.file.Files.delete;
import static java.nio.file.Files.move;
import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.apache.commons.io.FileUtils.copyInputStreamToFile;
import static org.apache.commons.io.FileUtils.deleteDirectory;
import static org.apache.commons.io.FileUtils.listFiles;
import static org.apache.commons.io.FileUtils.moveFileToDirectory;
import static org.rauschig.jarchivelib.ArchiveFormat.TAR;
import static org.rauschig.jarchivelib.ArchiverFactory.createArchiver;
import static org.rauschig.jarchivelib.CompressionType.BZIP2;
import static org.rauschig.jarchivelib.CompressionType.GZIP;
import static org.slf4j.LoggerFactory.getLogger;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Optional;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.rauschig.jarchivelib.Archiver;
import org.slf4j.Logger;
/**
* Downloader class.
*
* @author Boni Garcia ([email protected])
* @since 1.0.0
*/
public class Downloader {
final Logger log = getLogger(lookup().lookupClass());
DriverManagerType driverManagerType;
HttpClient httpClient;
public Downloader(DriverManagerType driverManagerType) {
this.driverManagerType = driverManagerType;
httpClient = WebDriverManager.getInstance(driverManagerType)
.getHttpClient();
}
public synchronized Optional download(URL url, String version,
String export, List driverName)
throws IOException, InterruptedException {
File targetFile = new File(getTarget(version, url));
String[] list = targetFile.getParentFile().list();
boolean download = !targetFile.getParentFile().exists()
|| !checkBinary(driverName, targetFile).isPresent()
|| config().isOverride();
log.trace("Downloading {} to {} ({})", url, targetFile, download);
if (!download && log.isDebugEnabled() && list != null) {
String content = listToString(Arrays.asList(list));
log.debug("Target folder content: {}", content);
}
Optional binary = (download)
? downloadAndExtract(url, targetFile, export)
: checkBinary(driverName, targetFile);
if (export != null && binary.isPresent()) {
return Optional.of(binary.get().toString());
}
return Optional.empty();
}
private Optional downloadAndExtract(URL url, File targetFile,
String export) throws IOException, InterruptedException {
File targetFolder = targetFile.getParentFile();
log.info("Downloading {} to folder {}", url, targetFolder);
File tempDir = createTempDirectory("").toFile();
File temporaryFile = new File(tempDir, targetFile.getName());
log.trace("Using temporal file {}", temporaryFile);
copyInputStreamToFile(httpClient.execute(httpClient.createHttpGet(url))
.getEntity().getContent(), temporaryFile);
File extractedFile;
if (!export.contains("edge")) {
extractedFile = extract(temporaryFile);
} else if (targetFile.getName().toLowerCase().endsWith(".msi")) {
extractedFile = extractMsi(temporaryFile);
} else {
extractedFile = temporaryFile;
}
File resultingBinary = new File(targetFolder, extractedFile.getName());
boolean binaryExists = resultingBinary.exists();
if (!binaryExists || config().isOverride()) {
if (binaryExists) {
log.debug("Overriding former binary {}", resultingBinary);
deleteFile(resultingBinary);
}
moveFileToDirectory(extractedFile, targetFolder, true);
}
if (!config().isExecutable(resultingBinary)) {
setFileExecutable(resultingBinary);
}
deleteFolder(tempDir);
log.info("Binary driver after extraction {}", resultingBinary);
return Optional.of(resultingBinary);
}
private Optional checkBinary(List driverName,
File targetFile) {
// Check if existing binary is valid
Collection listFiles = listFiles(targetFile.getParentFile(), null,
true);
for (File file : listFiles) {
for (String s : driverName) {
if (file.getName().startsWith(s)
&& config().isExecutable(file)) {
log.info("Using binary driver previously downloaded {}",
file);
return of(file);
}
}
}
log.trace("{} does not exist in cache", driverName);
return empty();
}
public String getTarget(String version, URL url) {
log.trace("getTarget {} {}", version, url);
String zip = url.getFile().substring(url.getFile().lastIndexOf('/'));
int iFirst = zip.indexOf('_');
int iSecond = zip.indexOf('-');
int iLast = zip.length();
if (iFirst != zip.lastIndexOf('_')) {
iLast = zip.lastIndexOf('_');
} else if (iSecond != -1) {
iLast = iSecond;
}
String folder = zip.substring(0, iLast).replace(".zip", "")
.replace(".tar.bz2", "").replace(".tar.gz", "")
.replace(".msi", "").replace(".exe", "")
.replace("_", separator);
String path = config().isAvoidOutputTree() ? getTargetPath() + zip
: getTargetPath() + folder + separator + version + zip;
String target = WebDriverManager.getInstance(driverManagerType)
.preDownload(path, version);
log.trace("Target file for URL {} version {} = {}", url, version,
target);
return new File(target).getPath();
}
public String getTargetPath() {
String targetPath = config().getTargetPath();
log.trace("Target path {}", targetPath);
// Create repository folder if not exits
File repository = new File(targetPath);
if (!repository.exists()) {
repository.mkdirs();
}
return targetPath;
}
public File extract(File compressedFile) throws IOException {
log.trace("Compressed file {}", compressedFile);
if (compressedFile.getName().toLowerCase().endsWith("tar.bz2")) {
unBZip2(compressedFile);
} else if (compressedFile.getName().toLowerCase().endsWith("tar.gz")) {
unTarGz(compressedFile);
} else if (compressedFile.getName().toLowerCase().endsWith("gz")) {
unGzip(compressedFile);
} else {
unZip(compressedFile);
}
deleteFile(compressedFile);
File result = WebDriverManager.getInstance(driverManagerType)
.postDownload(compressedFile).getAbsoluteFile();
log.trace("Resulting binary file {}", result);
return result;
}
public File unZip(File compressedFile) throws IOException {
File file = null;
try (ZipFile zipFolder = new ZipFile(compressedFile)) {
Enumeration> enu = zipFolder.entries();
while (enu.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry) enu.nextElement();
String name = zipEntry.getName();
long size = zipEntry.getSize();
long compressedSize = zipEntry.getCompressedSize();
log.trace("Unzipping {} (size: {} KB, compressed size: {} KB)",
name, size, compressedSize);
file = new File(compressedFile.getParentFile(), name);
if (!file.exists() || config().isOverride()) {
if (name.endsWith("/")) {
file.mkdirs();
continue;
}
File parent = file.getParentFile();
if (parent != null) {
parent.mkdirs();
}
try (InputStream is = zipFolder.getInputStream(zipEntry)) {
copyInputStreamToFile(is, file);
}
setFileExecutable(file);
} else {
log.debug("{} already exists", file);
}
}
}
return file;
}
public File unGzip(File archive) throws IOException {
log.trace("UnGzip {}", archive);
String fileName = archive.getName();
int iDash = fileName.indexOf('-');
if (iDash != -1) {
fileName = fileName.substring(0, iDash);
}
int iDot = fileName.indexOf('.');
if (iDot != -1) {
fileName = fileName.substring(0, iDot);
}
File target = new File(archive.getParentFile(), fileName);
try (GZIPInputStream in = new GZIPInputStream(
new FileInputStream(archive))) {
try (FileOutputStream out = new FileOutputStream(target)) {
for (int c = in.read(); c != -1; c = in.read()) {
out.write(c);
}
}
}
if (!target.getName().toLowerCase().contains(".exe")
&& target.exists()) {
setFileExecutable(target);
}
return target;
}
public File unTarGz(File archive) throws IOException {
Archiver archiver = createArchiver(TAR, GZIP);
archiver.extract(archive, archive.getParentFile());
log.trace("unTarGz {}", archive);
return archive;
}
public File unBZip2(File archive) throws IOException {
Archiver archiver = createArchiver(TAR, BZIP2);
archiver.extract(archive, archive.getParentFile());
log.trace("Unbzip2 {}", archive);
return archive;
}
public File extractMsi(File msi) throws IOException, InterruptedException {
File tmpMsi = new File(
createTempDirectory(msi.getName()).toFile().getAbsoluteFile()
+ separator + msi.getName());
move(msi.toPath(), tmpMsi.toPath());
log.trace("Temporal msi file: {}", tmpMsi);
Process process = getRuntime().exec(new String[] { "msiexec", "/a",
tmpMsi.toString(), "/qb", "TARGETDIR=" + msi.getParent() });
try {
process.waitFor();
} finally {
process.destroy();
}
deleteFile(tmpMsi);
deleteFile(msi);
Collection listFiles = listFiles(new File(msi.getParent()),
new String[] { "exe" }, true);
return listFiles.iterator().next();
}
protected void setFileExecutable(File file) {
log.trace("Setting file {} as executable", file);
if (!file.setExecutable(true)) {
log.warn("Error setting file {} as executable", file);
}
}
protected void renameFile(File from, File to) {
log.trace("Renaming file from {} to {}", from, to);
if (to.exists()) {
deleteFile(to);
}
if (!from.renameTo(to)) {
log.warn("Error renaming file from {} to {}", from, to);
}
}
protected void deleteFile(File file) {
log.trace("Deleting file {}", file);
try {
delete(file.toPath());
} catch (IOException e) {
throw new WebDriverManagerException(e);
}
}
protected void deleteFolder(File folder) {
assert folder.isDirectory();
log.trace("Deleting folder {}", folder);
try {
deleteDirectory(folder);
} catch (IOException e) {
throw new WebDriverManagerException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy