package com.faforever.client.update;
import com.faforever.client.fx.PlatformService;
import com.faforever.client.i18n.I18n;
import com.faforever.client.notification.Action;
import com.faforever.client.notification.NotificationService;
import com.faforever.client.notification.PersistentNotification;
import com.faforever.client.task.TaskService;
import com.google.common.annotations.VisibleForTesting;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import javax.annotation.Resource;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.nio.file.Path;
import java.util.Arrays;
import static com.faforever.client.io.Bytes.formatSize;
import static com.faforever.client.notification.Severity.INFO;
import static com.faforever.client.notification.Severity.WARN;
import static java.util.Collections.singletonList;
import static org.apache.commons.lang3.StringUtils.defaultString;
public class ClientUpdateServiceImpl implements ClientUpdateService {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final String DEVELOPMENT_VERSION_STRING = "dev";
@Resource
TaskService taskService;
@Resource
NotificationService notificationService;
@Resource
I18n i18n;
@Resource
PlatformService platformService;
@Resource
ApplicationContext applicationContext;
@VisibleForTesting
ComparableVersion currentVersion;
public ClientUpdateServiceImpl() {
currentVersion = new ComparableVersion(
defaultString(getClass().getPackage().getImplementationVersion(), DEVELOPMENT_VERSION_STRING)
);
logger.info("Current version: {}", currentVersion);
}
@Override
public void checkForUpdateInBackground() {
CheckForUpdateTask task = applicationContext.getBean(CheckForUpdateTask.class);
task.setCurrentVersion(currentVersion);
taskService.submitTask(task).getFuture()
.thenAccept(updateInfo -> {
if (updateInfo == null) {
return;
}
notificationService.addNotification(
new PersistentNotification(
i18n.get("clientUpdateAvailable.notification", updateInfo.getName(), formatSize(updateInfo.getSize(), i18n.getLocale())),
INFO,
Arrays.asList(
new Action(
i18n.get("clientUpdateAvailable.downloadAndInstall"),
event -> downloadAndInstallInBackground(updateInfo)
),
new Action(
i18n.get("clientUpdateAvailable.releaseNotes"),
Action.Type.OK_STAY,
event -> platformService.showDocument(updateInfo.getReleaseNotesUrl().toExternalForm())
)
)
)
);
}).exceptionally(throwable -> {
logger.warn("Client update check failed", throwable);
return null;
});
}
@Override
public ComparableVersion getCurrentVersion() {
return currentVersion;
}
private void install(Path binaryPath) {
// TODO probably need to make this executable on unix
String command = binaryPath.toAbsolutePath().toString();
try {
logger.info("Starting installer at {}", command);
new ProcessBuilder(command).inheritIO().start();
} catch (IOException e) {
logger.warn("Installation could not be started", e);
}
}
private void downloadAndInstallInBackground(UpdateInfo updateInfo) {
DownloadUpdateTask task = applicationContext.getBean(DownloadUpdateTask.class);
task.setUpdateInfo(updateInfo);
taskService.submitTask(task).getFuture()
.thenAccept(this::install)
.exceptionally(throwable -> {
logger.warn("Error while downloading client update", throwable);
notificationService.addNotification(
new PersistentNotification(i18n.get("clientUpdateDownloadFailed.notification"),
WARN,
singletonList(
new Action(i18n.get("clientUpdateDownloadFailed.retry"), event -> downloadAndInstallInBackground(updateInfo))
)
)
);
return null;
});
}
}