com.skcraft.launcher.update.Updater.java Source code

Java tutorial

Introduction

Here is the source code for com.skcraft.launcher.update.Updater.java

Source

/*
 * SK's Minecraft Launcher
 * Copyright (C) 2010-2014 Albert Pham <http://www.sk89q.com> and contributors
 * Please see LICENSE.txt for license information.
 */

package com.skcraft.launcher.update;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.skcraft.concurrency.DefaultProgress;
import com.skcraft.concurrency.ProgressFilter;
import com.skcraft.concurrency.ProgressObservable;
import com.skcraft.launcher.Instance;
import com.skcraft.launcher.Launcher;
import com.skcraft.launcher.LauncherException;
import com.skcraft.launcher.install.Installer;
import com.skcraft.launcher.model.minecraft.VersionManifest;
import com.skcraft.launcher.model.modpack.Manifest;
import com.skcraft.launcher.persistence.Persistence;
import com.skcraft.launcher.util.HttpRequest;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.extern.java.Log;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;

import static com.skcraft.launcher.util.HttpRequest.url;
import static com.skcraft.launcher.util.SharedLocale._;

@Log
public class Updater extends BaseUpdater implements Callable<Instance>, ProgressObservable {

    private final ObjectMapper mapper = new ObjectMapper();
    private final Installer installer;
    private final Launcher launcher;
    private final Instance instance;

    @Getter
    @Setter
    private boolean online;

    private List<URL> librarySources = new ArrayList<URL>();
    private List<URL> assetsSources = new ArrayList<URL>();

    private ProgressObservable progress = new DefaultProgress(-1, _("instanceUpdater.preparingUpdate"));

    public Updater(@NonNull Launcher launcher, @NonNull Instance instance) {
        super(launcher);

        this.installer = new Installer(launcher.getInstallerDir());
        this.launcher = launcher;
        this.instance = instance;

        librarySources.add(launcher.propUrl("librariesSource"));
        assetsSources.add(launcher.propUrl("assetsSource"));
    }

    @Override
    public Instance call() throws Exception {
        log.info("Checking for an update for '" + instance.getName() + "'...");

        boolean updateRequired = !instance.isInstalled();
        boolean updateDesired = (instance.isUpdatePending() || updateRequired);
        boolean updateCapable = (instance.getManifestURL() != null);

        if (!online && updateRequired) {
            log.info("Can't update " + instance.getTitle() + " because offline");
            String message = _("updater.updateRequiredButOffline");
            throw new LauncherException("Update required but currently offline", message);
        }

        if (updateDesired && !updateCapable) {
            if (updateRequired) {
                log.info("Update required for " + instance.getTitle() + " but there is no manifest");
                String message = _("updater.updateRequiredButNoManifest");
                throw new LauncherException("Update required but no manifest", message);
            } else {
                log.info("Can't update " + instance.getTitle() + ", but update is not required");
                return instance; // Can't update
            }
        }

        if (updateDesired) {
            log.info("Updating " + instance.getTitle() + "...");
            update(instance);
        } else {
            log.info("No update found for " + instance.getTitle());
        }

        return instance;
    }

    private VersionManifest readVersionManifest(Manifest manifest) throws IOException, InterruptedException {
        // Check whether the package manifest contains an embedded version manifest,
        // otherwise we'll have to download the one for the given Minecraft version
        VersionManifest version = manifest.getVersionManifest();
        if (version != null) {
            mapper.writeValue(instance.getVersionPath(), version);
            return version;
        } else {
            URL url = url(String.format(launcher.getProperties().getProperty("versionManifestUrl"),
                    manifest.getGameVersion()));

            return HttpRequest.get(url).execute().expectResponseCode(200).returnContent()
                    .saveContent(instance.getVersionPath()).asJson(VersionManifest.class);
        }
    }

    /**
     * Update the given instance.
     *
     * @param instance the instance
     * @throws IOException thrown on I/O error
     * @throws InterruptedException thrown on interruption
     * @throws ExecutionException thrown on execution error
     */
    protected void update(Instance instance) throws Exception {
        // Mark this instance as local
        instance.setLocal(true);
        Persistence.commitAndForget(instance);

        // Read manifest
        log.info("Reading package manifest...");
        progress = new DefaultProgress(-1, _("instanceUpdater.readingManifest"));
        Manifest manifest = installPackage(installer, instance);

        // Update instance from manifest
        manifest.update(instance);

        // Read version manifest
        log.info("Reading version manifest...");
        progress = new DefaultProgress(-1, _("instanceUpdater.readingVersion"));
        VersionManifest version = readVersionManifest(manifest);

        progress = new DefaultProgress(-1, _("instanceUpdater.buildingDownloadList"));

        // Install the .jar
        File jarPath = launcher.getJarPath(version);
        URL jarSource = launcher.propUrl("jarUrl", version.getId());
        log.info("JAR at " + jarPath.getAbsolutePath() + ", fetched from " + jarSource);
        installJar(installer, jarPath, jarSource);

        // Download libraries
        log.info("Enumerating libraries to download...");

        URL url = manifest.getLibrariesUrl();
        if (url != null) {
            log.info("Added library source: " + url);
            librarySources.add(url);
        }

        progress = new DefaultProgress(-1, _("instanceUpdater.collectingLibraries"));
        installLibraries(installer, version, launcher.getLibrariesDir(), librarySources);

        // Download assets
        log.info("Enumerating assets to download...");
        progress = new DefaultProgress(-1, _("instanceUpdater.collectingAssets"));
        installAssets(installer, version, launcher.propUrl("assetsIndexUrl", version.getAssetsIndex()),
                assetsSources);

        log.info("Executing download phase...");
        progress = ProgressFilter.between(installer.getDownloader(), 0, 0.98);
        installer.download();

        log.info("Executing install phase...");
        progress = ProgressFilter.between(installer, 0.98, 1);
        installer.execute();

        log.info("Completing...");
        complete();

        // Update the instance's information
        log.info("Writing instance information...");
        instance.setVersion(manifest.getVersion());
        instance.setUpdatePending(false);
        instance.setInstalled(true);
        instance.setLocal(true);
        Persistence.commitAndForget(instance);

        log.log(Level.INFO, instance.getName() + " has been updated to version " + manifest.getVersion() + ".");
    }

    @Override
    public double getProgress() {
        return progress.getProgress();
    }

    @Override
    public String getStatus() {
        return progress.getStatus();
    }

}