Package com.skcraft.launcher.update

Source Code of com.skcraft.launcher.update.BaseUpdater

/*
* 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.google.common.base.Strings;
import com.skcraft.launcher.AssetsRoot;
import com.skcraft.launcher.Instance;
import com.skcraft.launcher.Launcher;
import com.skcraft.launcher.LauncherException;
import com.skcraft.launcher.dialog.FeatureSelectionDialog;
import com.skcraft.launcher.dialog.ProgressDialog;
import com.skcraft.launcher.install.*;
import com.skcraft.launcher.model.minecraft.Asset;
import com.skcraft.launcher.model.minecraft.AssetsIndex;
import com.skcraft.launcher.model.minecraft.Library;
import com.skcraft.launcher.model.minecraft.VersionManifest;
import com.skcraft.launcher.model.modpack.Feature;
import com.skcraft.launcher.model.modpack.Manifest;
import com.skcraft.launcher.model.modpack.ManifestEntry;
import com.skcraft.launcher.persistence.Persistence;
import com.skcraft.launcher.util.Environment;
import com.skcraft.launcher.util.HttpRequest;
import lombok.NonNull;
import lombok.extern.java.Log;

import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.logging.Level;

import static com.skcraft.launcher.LauncherUtils.checkInterrupted;
import static com.skcraft.launcher.LauncherUtils.concat;
import static com.skcraft.launcher.util.SharedLocale._;

/**
* The base implementation of the various routines involved in downloading
* and updating Minecraft (including the launcher's modpacks), such as asset
* downloading, .jar downloading, and so on.
* </p>
* Updating actually starts in {@link com.skcraft.launcher.update.Updater},
* which is the update worker. This class exists to allow updaters that don't
* use the launcher's default modpack format to reuse these update
* routines. (It also makes the size of the <code>Updater</code> class smaller.)
*/
@Log
public abstract class BaseUpdater {

    private static final long JAR_SIZE_ESTIMATE = 5 * 1024 * 1024;
    private static final long LIBRARY_SIZE_ESTIMATE = 3 * 1024 * 1024;

    private final Launcher launcher;
    private final Environment environment = Environment.getInstance();
    private final List<Runnable> executeOnCompletion = new ArrayList<Runnable>();

    protected BaseUpdater(@NonNull Launcher launcher) {
        this.launcher = launcher;
    }

    protected void complete() {
        for (Runnable runnable : executeOnCompletion) {
            runnable.run();
        }
    }

    protected Manifest installPackage(@NonNull Installer installer, @NonNull Instance instance) throws Exception {
        final File contentDir = instance.getContentDir();
        final File logPath = new File(instance.getDir(), "install_log.json");
        final File cachePath = new File(instance.getDir(), "update_cache.json");
        final File featuresPath = new File(instance.getDir(), "features.json");

        final InstallLog previousLog = Persistence.read(logPath, InstallLog.class);
        final InstallLog currentLog = new InstallLog();
        currentLog.setBaseDir(contentDir);
        final UpdateCache updateCache = Persistence.read(cachePath, UpdateCache.class);
        final FeatureCache featuresCache = Persistence.read(featuresPath, FeatureCache.class);

        Manifest manifest = HttpRequest
                .get(instance.getManifestURL())
                .execute()
                .expectResponseCode(200)
                .returnContent()
                .saveContent(instance.getManifestPath())
                .asJson(Manifest.class);

        if (manifest.getMinimumVersion() > Launcher.PROTOCOL_VERSION) {
            throw new LauncherException("Update required", _("errors.updateRequiredError"));
        }

        if (manifest.getBaseUrl() == null) {
            manifest.setBaseUrl(instance.getManifestURL());
        }

        final List<Feature> features = manifest.getFeatures();
        if (!features.isEmpty()) {
            for (Feature feature : features) {
                Boolean last = featuresCache.getSelected().get(feature.getName());
                if (last != null) {
                    feature.setSelected(last);
                }
            }

            Collections.sort(features);

            SwingUtilities.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    new FeatureSelectionDialog(ProgressDialog.getLastDialog(), features).setVisible(true);
                }
            });

            for (Feature feature : features) {
                featuresCache.getSelected().put(Strings.nullToEmpty(feature.getName()), feature.isSelected());
            }
        }

        for (ManifestEntry entry : manifest.getTasks()) {
            entry.install(installer, currentLog, updateCache, contentDir);
        }

        executeOnCompletion.add(new Runnable() {
            @Override
            public void run() {
                for (Map.Entry<String, Set<String>> entry : previousLog.getEntrySet()) {
                    for (String path : entry.getValue()) {
                        if (!currentLog.has(path)) {
                            new File(contentDir, path).delete();
                        }
                    }
                }

                writeDataFile(logPath, currentLog);
                writeDataFile(cachePath, updateCache);
                writeDataFile(featuresPath, featuresCache);
            }
        });

        return manifest;
    }

    protected void installJar(@NonNull Installer installer,
                              @NonNull File jarFile,
                              @NonNull URL url) throws InterruptedException {
        // If the JAR does not exist, install it
        if (!jarFile.exists()) {
            List<File> targets = new ArrayList<File>();

            File tempFile = installer.getDownloader().download(url, "", JAR_SIZE_ESTIMATE, jarFile.getName());
            installer.queue(new FileMover(tempFile, jarFile));
            log.info("Installing " + jarFile.getName() + " from " + url);
        }
    }

    protected void installAssets(@NonNull Installer installer,
                                 @NonNull VersionManifest versionManifest,
                                 @NonNull URL indexUrl,
                                 @NonNull List<URL> sources) throws IOException, InterruptedException {
        AssetsRoot assetsRoot = launcher.getAssets();

        AssetsIndex index = HttpRequest
                .get(indexUrl)
                .execute()
                .expectResponseCode(200)
                .returnContent()
                .saveContent(assetsRoot.getIndexPath(versionManifest))
                .asJson(AssetsIndex.class);

        // Keep track of duplicates
        Set<String> downloading = new HashSet<String>();

        for (Map.Entry<String, Asset> entry : index.getObjects().entrySet()) {
            checkInterrupted();

            String hash = entry.getValue().getHash();
            String path = String.format("%s/%s", hash.subSequence(0, 2), hash);
            File targetFile = assetsRoot.getObjectPath(entry.getValue());

            if (!targetFile.exists() && !downloading.contains(path)) {
                List<URL> urls = new ArrayList<URL>();
                for (URL sourceUrl : sources) {
                    try {
                        urls.add(concat(sourceUrl, path));
                    } catch (MalformedURLException e) {
                        log.log(Level.WARNING, "Bad source URL for library: " + sourceUrl);
                    }
                }

                File tempFile = installer.getDownloader().download(
                        urls, "", entry.getValue().getSize(), entry.getKey());
                installer.queue(new FileMover(tempFile, targetFile));
                log.info("Fetching " + path + " from " + urls);
                downloading.add(path);
            }
        }
    }

    protected void installLibraries(@NonNull Installer installer,
                                    @NonNull VersionManifest versionManifest,
                                    @NonNull File librariesDir,
                                    @NonNull List<URL> sources) throws InterruptedException {

        for (Library library : versionManifest.getLibraries()) {
            if (library.matches(environment)) {
                checkInterrupted();

                String path = library.getPath(environment);
                File targetFile = new File(librariesDir, path);

                if (!targetFile.exists()) {
                    List<URL> urls = new ArrayList<URL>();
                    for (URL sourceUrl : sources) {
                        try {
                            urls.add(concat(sourceUrl, path));
                        } catch (MalformedURLException e) {
                            log.log(Level.WARNING, "Bad source URL for library: " + sourceUrl);
                        }
                    }

                    File tempFile = installer.getDownloader().download(urls, "", LIBRARY_SIZE_ESTIMATE,
                            library.getName() + ".jar");
                    installer.queue(new FileMover( tempFile, targetFile));
                    log.info("Fetching " + path + " from " + urls);
                }
            }
        }
    }

    private static void writeDataFile(File path, Object object) {
        try {
            Persistence.write(path, object);
        } catch (IOException e) {
            log.log(Level.WARNING, "Failed to write to " + path.getAbsolutePath() +
                    " for object " + object.getClass().getCanonicalName(), e);
        }
    }

}
TOP

Related Classes of com.skcraft.launcher.update.BaseUpdater

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.