All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.sealights.agents.plugin.upgrade.AbstractUpgradeManager Maven / Gradle / Ivy

package io.sealights.agents.plugin.upgrade;

import io.sealights.agents.plugin.entities.Version;
import io.sealights.agents.plugin.upgrade.entities.AgentInfo;
import io.sealights.agents.plugin.upgrade.entities.UpgradeConfiguration;
import io.sealights.agents.plugin.upgrade.entities.UpgradeResponse;
import io.sealights.agents.plugin.upgrade.services.UpgradeProxy;
import io.sealights.agents.plugin.upgrade.utils.ArchiveUtils;
import io.sealights.agents.plugin.upgrade.utils.FileAndFolderUtils;
import io.sealights.agents.plugin.upgrade.utils.JarUtils;
import io.sealights.agents.plugin.upgrade.utils.UserMessageHelper;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
import java.util.jar.JarFile;

import static io.sealights.agents.plugin.upgrade.ComponentName.BUILD_SCANNER_COMPONENT_NAME;
import static io.sealights.agents.plugin.upgrade.ComponentName.TEST_LISTENER_COMPONENT_NAME;

/**
 * Created by shahar on 7/31/2016.
 */
public abstract class AbstractUpgradeManager {

    private UpgradeProxy upgradeProxy;
    protected UpgradeConfiguration upgradeConfiguration;
    protected final UserMessageHelper userMessageHelper;
    private static final int VERSIONS_HISTORY_TO_SAVE_BESIDE_RECOMMENDED = 2;

    public static final String SL_RELATIVE_CACHE_FOLDER = "sl-cache";
    public static final String MAVEN_PLUGIN_AGENTS_RELATIVE_CACHE_FOLDER = "maven-plugin";
    protected String embeddedVersion;

    public AbstractUpgradeManager(UpgradeProxy upgradeProxy, UpgradeConfiguration upgradeConfiguration, UserMessageHelper userMessageHelper) {
        this.upgradeProxy = upgradeProxy;
        this.upgradeConfiguration = upgradeConfiguration;
        this.userMessageHelper = userMessageHelper;
        this.embeddedVersion = AbstractUpgradeManager.class.getPackage().getImplementationVersion();
    }

    /**
     * Ensures that the latest version of the agent is present locally (downloads it if needed)
     *
     * @return the path to the JAR file
     * @throws Exception When the server could not be contacted or various IO exceptions (permissions, network, etc.)
     */
    public String ensureLatestAgentPresentLocally(){
        try {
            UpgradeResponse upgradeResponse = upgradeProxy.getRecommendedVersion("sealights-java");
            if (!isValidResponse(upgradeResponse)) {
                throw new Exception("Could not get latest version info from server. " +
                        "The response from the server has invalid fields.");
            }

            String jarsFolder = FileAndFolderUtils.join(upgradeConfiguration.getFilesStorage(),
                    SL_RELATIVE_CACHE_FOLDER, MAVEN_PLUGIN_AGENTS_RELATIVE_CACHE_FOLDER);
            if (!FileAndFolderUtils.verifyFolderExists(jarsFolder)){
                throw new Exception("Could not verify that cache folder exists: '" + jarsFolder + "'.");
            }

            String foundAgent = findOrDownloadAgentByVersion(jarsFolder, upgradeResponse);
            return foundAgent;
        } catch (FileNotFoundException e) {
            throw new RuntimeException("Error while trying to resolve Sealights recommended agents version. " +
                    "Probably the server did not found recommended agents version.");
        }
        catch (Exception e) {
            throw new RuntimeException("Error while trying to resolve Sealights recommended agents version.", e);
        }
    }

    /*
    * Response will be valid if:
    * 1. Version is in the right format.
    * 2. The agent name can be found in the ComponentName enum.
    * We don't check if url is malformed because maybe download won't be needed.
    * */
    private boolean isValidResponse(UpgradeResponse upgradeResponse) {
        boolean isValid = true;
        if (upgradeResponse == null) {
            userMessageHelper.printWarn("Got response 'null'.");
            return false;
        }

        AgentInfo agentInfo = upgradeResponse.getAgent();
        if (agentInfo == null) {
            userMessageHelper.printWarn("Got response with agent information 'null'.");
            return false;
        }

        if (!Version.isValidVersion(agentInfo.getVersion())) {
            userMessageHelper.printWarn("Got response with invalid version '" + agentInfo.getVersion() + "'.");
            isValid = false;
        }

        if (!isValidAgentName(agentInfo.getName())) {
            userMessageHelper.printWarn("Got response with invalid agent name '" + agentInfo.getName() + "'.");
            isValid = false;
        }

        return isValid;
    }

    private boolean isValidAgentName(String name) {
        return "sealights-java".equals(name);
    }

    private void rearrangeJarsFolder(String jarsFolder) {
        File folder = new File(jarsFolder);
        File[] filesInFolder = folder.listFiles();
        if (filesInFolder == null){
            userMessageHelper.printWarn("Unable to rearrange the cache folder since 'filesInFolder' is null.");
            return;
        }
        TreeMap> versions = createAgentsVersionsSortedMap(filesInFolder);
        if (versions.size() > VERSIONS_HISTORY_TO_SAVE_BESIDE_RECOMMENDED) {
            performJarsRearrangement(versions);
        }
    }

    private void performJarsRearrangement(TreeMap> versions) {
        versions = getVersionsToDelete(versions);
        Iterator it = versions.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry> pair = (Map.Entry>) it.next();
            List agentsToDelete = pair.getValue();
            for (File agent : agentsToDelete)
                tryDeleteFile(agent, "old agent");
        }
    }

    private TreeMap> getVersionsToDelete(TreeMap> versions) {
        for (int i = 0; i < VERSIONS_HISTORY_TO_SAVE_BESIDE_RECOMMENDED; i++) {
            versions.remove(versions.lastKey());
        }
        return versions;
    }

    private TreeMap> createAgentsVersionsSortedMap(File[] filesInFolder) {
        TreeMap> versionsTree = new TreeMap<>();
        for (File f : filesInFolder) {

            if (f == null || !f.isFile())
                continue;

            String filename = f.getName();
            boolean isAgentJar = filename.startsWith("sl-") && filename.endsWith(".jar");
            if (!isAgentJar)
                continue;

            String detectedVersion = detectVersionFromAgentFileName(filename);
            if (!Version.isValidVersion(detectedVersion)){
                continue;
            }
            Version v = new Version(detectedVersion);
            addAgentToVersionAgentTree(versionsTree, v, f);
        }

        return versionsTree;
    }

    private String detectVersionFromAgentFileName(String fileName) {
        fileName = fileName.replace(BUILD_SCANNER_COMPONENT_NAME.toString() + "-", "");
        fileName = fileName.replace(TEST_LISTENER_COMPONENT_NAME.toString() + "-", "");
        return fileName.replace(".jar", "");
    }

    private void addAgentToVersionAgentTree(TreeMap> versionsTree, Version version, File agent) {
        List listToAdd = tryGetMatchingVersionInVersionAgentTree(versionsTree, version);

        if (listToAdd != null) {
            listToAdd.add(agent);
        } else {
            //create new version key
            List filesRelatedToVersion = new ArrayList<>();
            filesRelatedToVersion.add(agent);
            versionsTree.put(version, filesRelatedToVersion);
        }
    }

    private List tryGetMatchingVersionInVersionAgentTree(TreeMap> versionsTree, Version version) {
        for (Version v : versionsTree.keySet()) {
            if (v.equals(version))
                return versionsTree.get(v);
        }
        return null;
    }

    /**
     * Based on (@link upgradeResponse), checks if the file exists. If it doesn't, it downloads the file.
     *
     * @param jarsFolder      Cache folder where agents are stored
     * @param upgradeResponse
     * @return Agent Jar file path
     * @throws Exception
     */
    protected String findOrDownloadAgentByVersion(String jarsFolder, UpgradeResponse upgradeResponse) {

        JarFile jarFile;
        AgentInfo agentInfo = upgradeResponse.getAgent();
        String recommendedVersion = agentInfo.getVersion();

        userMessageHelper.println("Check if agent '" + getComponentName()
                + " with version '" + recommendedVersion + "' exists in files storage.");

        jarFile = tryGetRecommendedAgentFromFolder(jarsFolder, recommendedVersion);
        if (jarFile != null) {
            userMessageHelper.println("Found '" + getComponentName()
                    + "' with version '" + recommendedVersion + "' in files storage.");
            return jarFile.getName();
        }

        userMessageHelper.println("Trying to get agent '" + getComponentName()
                + "' with version '" + recommendedVersion + "' from remote storage.");
        jarFile = tryGetRecommendedAgentFromServer(jarsFolder, upgradeResponse);
        if (jarFile != null) {
            userMessageHelper.println("'" + getComponentName() + "' with version '" + recommendedVersion + "' has been downloaded.");
            return jarFile.getName();
        }

        throw new RuntimeException("Could not download latest agent version.");
    }

    protected JarFile tryGetRecommendedAgentFromServer(String jarsFolder, UpgradeResponse upgradeResponse){

        AgentInfo agentInfo = upgradeResponse.getAgent();
        if (agentInfo == null){
            userMessageHelper.printError("Unable to get recommended agent from server. " +
                    "Recommended agent information was 'null'.");
            return null;
        }
        String version = agentInfo.getVersion();
        String url = agentInfo.getUrl();
        String zipFilePath = getAgentsTargetZipFilePath(jarsFolder);

        // try to download the agent to the target zip file.
        userMessageHelper.println("Trying to upgrade to version '" + version + "' from url '" + url + "'.");
        if (!upgradeProxy.downloadAgent(url, zipFilePath)) {
            userMessageHelper.printWarn("Failed to download agent with version '" + version + "'.");
        }else{
            userMessageHelper.println("Download completed successfully.");
            rearrangeJarsFolder(jarsFolder);

            // try to unzip the downloaded agent.
            ArchiveUtils archiveUtils = new ArchiveUtils(userMessageHelper);
            archiveUtils.unzip(zipFilePath, jarsFolder);
            tryDeleteDownloadedZip(zipFilePath);

            File newAgent = getPathToDownloadedAgent(jarsFolder, version);
            if (newAgent.isFile())
                return createTempJarFileFromExternalJar(newAgent);

            userMessageHelper.printWarn("Failed to unzip agent with version '" + version + "'.");
        }
        return null;
    }

    protected JarFile tryGetRecommendedAgentFromFolder(String jarsFolder, String recommendedVersion) {
        String jarNameToFind = getComponentNameDash() + recommendedVersion + ".jar";
        File recommendedAgent = FileAndFolderUtils.findFileInFolder(jarsFolder, jarNameToFind);
        if (recommendedAgent == null){
            userMessageHelper.println("Didn't find the recommended agent '" + jarNameToFind
                    + "' in folder '" + jarsFolder + "'.");
            return null;
        }
        if (!recommendedAgent.isFile()) {
            userMessageHelper.println("Didn't find the recommended agent '"
                    + recommendedAgent.getAbsolutePath() + "' in file system or it is not a valid file.");
            return null;
        }

        return createTempJarFileFromExternalJar(recommendedAgent);
    }

    private void tryDeleteDownloadedZip(String zipFilePath){
        File zipFileToDelete = new File(zipFilePath);
        tryDeleteFile(zipFileToDelete, "agent zip file");
    }

    private String getAgentsTargetZipFilePath(String jarsFolder){
        String fileName = getFileToDownloadName() + ".zip";
        return FileAndFolderUtils.join(jarsFolder, fileName);
    }

    private File getPathToDownloadedAgent(String jarsFolder, String version) {
        Version recommendedVersion = new Version(version);
        String newAgentName = getComponentNameDash() + recommendedVersion.get() + ".jar";
        String pathToNewAgent = FileAndFolderUtils.join(jarsFolder, newAgentName);
        return new File(pathToNewAgent);
    }

    protected JarFile createTempJarFileFromExternalJar(File recommendedAgent){
        String agentPath = upgradeConfiguration.getFilesStorage();
        return loadExternalJar(recommendedAgent, agentPath, false);
    }

    protected JarFile loadExternalJar(File recommendedAgent, String agentPath, boolean useOverrideListenerPath){

        return JarUtils.loadExternalJar(recommendedAgent, getComponentName(),
                userMessageHelper, agentPath, useOverrideListenerPath);
    }

    private void tryDeleteFile(File oldAgent, String descriptor) {
        try {
            if (oldAgent.delete()) {
                userMessageHelper.println("Successfully deleted " + descriptor + ": '" + oldAgent.getAbsolutePath() + "'.");
                return;
            }
            if (oldAgent.exists()) {
                userMessageHelper.println("Failed to delete " + descriptor + ": '" + oldAgent.getAbsolutePath() + "'.");
            }

        } catch (Exception e) {
            userMessageHelper.printError("Failed to delete " + descriptor + ": '" + oldAgent.getAbsolutePath() + "'. Error: ", e);
        }
    }

    abstract protected ComponentName getComponentNameEnum();

    abstract String getFileToDownloadName();

    protected String getComponentName() {
        return getComponentNameEnum().toString();
    }

    private String getComponentNameDash() {
        return getComponentName() + "-";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy