net.technicpack.solder.cache.CachedSolderPackApi.java Source code

Java tutorial

Introduction

Here is the source code for net.technicpack.solder.cache.CachedSolderPackApi.java

Source

/*
 * This file is part of Technic Launcher Core.
 * Copyright 2015 Syndicate, LLC
 *
 * Technic Launcher Core is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Technic Launcher Core is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License,
 * as well as a copy of the GNU Lesser General Public License,
 * along with Technic Launcher Core.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.technicpack.solder.cache;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.gson.JsonSyntaxException;
import net.technicpack.launchercore.exception.BuildInaccessibleException;
import net.technicpack.launchercore.install.LauncherDirectories;
import net.technicpack.rest.RestfulAPIException;
import net.technicpack.rest.io.Modpack;
import net.technicpack.solder.ISolderPackApi;
import net.technicpack.solder.io.SolderPackInfo;
import net.technicpack.utilslib.Utils;
import org.apache.commons.io.FileUtils;
import org.joda.time.DateTime;
import org.joda.time.Seconds;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

public class CachedSolderPackApi implements ISolderPackApi {

    private LauncherDirectories directories;
    private ISolderPackApi innerApi;
    private int cacheInSeconds;
    private String packSlug;

    private SolderPackInfo rootInfoCache = null;
    private DateTime lastInfoAccess = new DateTime(0);

    private Cache<String, Modpack> buildCache;
    private Cache<String, Boolean> deadBuildCache;

    public CachedSolderPackApi(LauncherDirectories directories, ISolderPackApi innerApi, int cacheInSeconds,
            String packSlug) {
        this.directories = directories;
        this.innerApi = innerApi;
        this.cacheInSeconds = cacheInSeconds;
        this.packSlug = packSlug;

        buildCache = CacheBuilder.newBuilder().concurrencyLevel(4).maximumSize(300)
                .expireAfterWrite(cacheInSeconds, TimeUnit.SECONDS).build();

        deadBuildCache = CacheBuilder.newBuilder().concurrencyLevel(4).maximumSize(300)
                .expireAfterWrite(cacheInSeconds / 10, TimeUnit.SECONDS).build();
    }

    @Override
    public String getMirrorUrl() {
        return innerApi.getMirrorUrl();
    }

    @Override
    public SolderPackInfo getPackInfoForBulk() throws RestfulAPIException {
        if (rootInfoCache != null)
            return rootInfoCache;

        loadForeverCache();

        if (rootInfoCache != null)
            return rootInfoCache;

        return pullAndCache();
    }

    @Override
    public SolderPackInfo getPackInfo() throws RestfulAPIException {
        if (Seconds.secondsBetween(lastInfoAccess, DateTime.now()).isLessThan(Seconds.seconds(cacheInSeconds))) {
            if (rootInfoCache != null)
                return rootInfoCache;
        }

        if (Seconds.secondsBetween(lastInfoAccess, DateTime.now()).isLessThan(Seconds.seconds(cacheInSeconds / 10)))
            return rootInfoCache;

        try {
            return pullAndCache();
        } catch (RestfulAPIException ex) {
            ex.printStackTrace();

            return getPackInfoForBulk();
        }
    }

    private SolderPackInfo pullAndCache() throws RestfulAPIException {
        try {
            rootInfoCache = innerApi.getPackInfoForBulk();
            saveForeverCache(rootInfoCache);
            return rootInfoCache;
        } finally {
            lastInfoAccess = DateTime.now();
        }
    }

    private void loadForeverCache() {
        File cacheFile = new File(new File(new File(directories.getAssetsDirectory(), "packs"), packSlug),
                "soldercache.json");
        if (!cacheFile.exists())
            return;

        try {
            String packCache = FileUtils.readFileToString(cacheFile, Charset.forName("UTF-8"));
            rootInfoCache = Utils.getGson().fromJson(packCache, SolderPackInfo.class);

            if (rootInfoCache != null)
                rootInfoCache.setLocal();
        } catch (IOException ex) {
        } catch (JsonSyntaxException ex) {
        }
    }

    private void saveForeverCache(SolderPackInfo info) {
        File cacheFile = new File(new File(new File(directories.getAssetsDirectory(), "packs"), info.getName()),
                "soldercache.json");

        String packCache = Utils.getGson().toJson(info);

        try {
            FileUtils.writeStringToFile(cacheFile, packCache, Charset.forName("UTF-8"));
        } catch (IOException e) {
            return;
        }
    }

    @Override
    public Modpack getPackBuild(String build) throws BuildInaccessibleException {

        Boolean isDead = deadBuildCache.getIfPresent(build);

        if (isDead != null && isDead.booleanValue())
            return null;

        Modpack modpack = buildCache.getIfPresent(build);

        if (modpack != null) {
            return modpack;
        }

        try {
            modpack = innerApi.getPackBuild(build);

            if (modpack != null) {
                buildCache.put(build, modpack);
            }

            return modpack;
        } finally {
            deadBuildCache.put(build, modpack == null);
        }
    }
}