<commit_before>package org.jfrog.hudson.maven3;

import hudson.AbortException;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.maven.MavenEmbedderException;
import hudson.maven.MavenEmbedderUtils;
import hudson.maven.MavenModuleSet;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.BuildListener;
import hudson.model.Computer;
import hudson.model.Hudson;
import hudson.model.Result;
import hudson.remoting.Which;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
import hudson.tasks.Maven;
import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.jfrog.build.api.util.NullLog;
import org.jfrog.build.client.ArtifactoryClientConfiguration;
import org.jfrog.build.extractor.maven.BuildInfoRecorder;
import org.jfrog.hudson.ArtifactoryBuilder;
import org.jfrog.hudson.ArtifactoryServer;
import org.jfrog.hudson.ResolverOverrider;
import org.jfrog.hudson.ServerDetails;
import org.jfrog.hudson.util.CredentialResolver;
import org.jfrog.hudson.util.Credentials;
import org.jfrog.hudson.util.ExtractorUtils;
import org.jfrog.hudson.util.PluginDependencyHelper;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author <NAME>
 */
public class ArtifactoryMaven3NativeConfigurator extends BuildWrapper implements ResolverOverrider {

    /**
     * The minimum Maven version that is required for the {@link AbstractRepositoryListener} to be
     * present.
     */
    private static final String MINIMUM_MAVEN_VERSION = "3.0.2";
    private final ServerDetails details;
    private final Credentials overridingResolverCredentials;

    @DataBoundConstructor
    public ArtifactoryMaven3NativeConfigurator(ServerDetails details, Credentials overridingResolverCredentials) {
        this.details = details;
        this.overridingResolverCredentials = overridingResolverCredentials;
    }

    public ServerDetails getDetails() {
        return details;
    }

    public String getDownloadRepositoryKey() {
        return details != null ? details.downloadRepositoryKey : null;
    }

    public String getArtifactoryName() {
        return details != null ? details.artifactoryName : null;
    }

    public String getRepositoryKey() {
        return details != null ? details.repositoryKey : null;
    }

    @Override
    public Collection<? extends Action> getProjectActions(AbstractProject project) {
        return Collections.emptyList();
    }

    public boolean isOverridingDefaultResolver() {
        return getOverridingResolverCredentials() != null;
    }

    public Credentials getOverridingResolverCredentials() {
        return overridingResolverCredentials;
    }

    @Override
    public Environment setUp(final AbstractBuild build, Launcher launcher, BuildListener listener)
            throws IOException, InterruptedException {
        final MavenModuleSet project = (MavenModuleSet) build.getProject();
        EnvVars envVars = build.getEnvironment(listener);
        try {
            // get the maven installation
            Maven.MavenInstallation mavenInstallation = getMavenInstallation(project, envVars, listener);
            // if the installation is not the minimal required version do nothing.
            if (!(MavenEmbedderUtils.isAtLeastMavenVersion(mavenInstallation.getHomeDir(), MINIMUM_MAVEN_VERSION))) {
                return new Environment() {
                    // return the empty environment
                };
            }
        } catch (MavenEmbedderException e) {
            throw new RuntimeException(e);
        }
        final String mavenOpts = project.getMavenOpts();
        try {
            project.setMavenOpts(appendNewMavenOpts(project, build));
        } catch (IOException e) {
            throw new RuntimeException("Unable to manipulate maven_opts for project: " + project, e);
        }
        final File classWorldsFile = File.createTempFile("classworlds", "conf");
        URL resource = getClass().getClassLoader().getResource("org/jfrog/hudson/maven3/classworlds-native.conf");
        final String classworldsConfPath = ExtractorUtils.copyClassWorldsFile(build, resource, classWorldsFile);
        build.setResult(Result.SUCCESS);
        return new Environment() {
            @Override
            public void buildEnvVars(Map<String, String> env) {
                super.buildEnvVars(env);
                final ArtifactoryServer artifactoryServer = getArtifactoryServer();
                Credentials preferredResolver = CredentialResolver
                        .getPreferredResolver(ArtifactoryMaven3NativeConfigurator.this, artifactoryServer);

                ArtifactoryClientConfiguration configuration = new ArtifactoryClientConfiguration(new NullLog());
                configuration.setContextUrl(artifactoryServer.getUrl());
                configuration.resolver.setRepoKey(getDownloadRepositoryKey());
                configuration.resolver.setUsername(preferredResolver.getUsername());
                configuration.resolver.setPassword(preferredResolver.getPassword());
                ExtractorUtils.addBuildRootIfNeeded(build, configuration);
                env.putAll(configuration.getAllProperties());
                ExtractorUtils.addCustomClassworlds(env, classworldsConfPath);
            }

            @Override
            public boolean tearDown(AbstractBuild build, BuildListener listener)
                    throws IOException, InterruptedException {
                final MavenModuleSet project = (MavenModuleSet) build.getProject();
                project.setMavenOpts(mavenOpts);
                FileUtils.deleteQuietly(classWorldsFile);
                return super.tearDown(build, listener);
            }
        };
    }

    /**
     * Get the {@link hudson.model.EnvironmentSpecific} and {@link hudson.slaves.NodeSpecific} Maven installation. First
     * get the descriptor from the global Jenkins. Then populate it accordingly from the specific environment node that
     * the process is currently running in e.g. the MAVEN_HOME variable may be defined only in the remote node and
     * Jenkins is not persisting it as part of its installations.
     *
     * @param project  The Maven project that the maven installation is taken from.
     * @param vars     The build's environment variables.
     * @param listener The build's event listener
     * @throws AbortException If the {@link Maven.MavenInstallation} that is taken from the project is {@code null} then
     *                        this exception is thrown.
     */
    private Maven.MavenInstallation getMavenInstallation(MavenModuleSet project, EnvVars vars, BuildListener listener)
            throws IOException, InterruptedException {
        Maven.MavenInstallation mavenInstallation = project.getMaven();
        if (mavenInstallation == null) {
            throw new AbortException("A Maven installation needs to be available for this project to be built.\n" +
                    "Either your server has no Maven installations defined, or the requested Maven version does not exist.");
        }
        return mavenInstallation.forEnvironment(vars).forNode(Computer.currentComputer().getNode(), listener);
    }<commit_msg>HAP-178 - "Resolve artifacts from Artifactory" results in "mavenHome must exists" error<commit_after>package org.jfrog.hudson.maven3;

import hudson.AbortException;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.maven.MavenInformation;
import hudson.maven.MavenModuleSet;
import hudson.maven.MavenVersionCallable;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.BuildListener;
import hudson.model.Computer;
import hudson.model.Hudson;
import hudson.model.Result;
import hudson.remoting.Which;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
import hudson.tasks.Maven;
import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.jfrog.build.api.util.NullLog;
import org.jfrog.build.client.ArtifactoryClientConfiguration;
import org.jfrog.build.extractor.maven.BuildInfoRecorder;
import org.jfrog.hudson.ArtifactoryBuilder;
import org.jfrog.hudson.ArtifactoryServer;
import org.jfrog.hudson.ResolverOverrider;
import org.jfrog.hudson.ServerDetails;
import org.jfrog.hudson.util.CredentialResolver;
import org.jfrog.hudson.util.Credentials;
import org.jfrog.hudson.util.ExtractorUtils;
import org.jfrog.hudson.util.PluginDependencyHelper;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author <NAME>
 */
public class ArtifactoryMaven3NativeConfigurator extends BuildWrapper implements ResolverOverrider {

    /**
     * The minimum Maven version that is required for the {@link AbstractRepositoryListener} to be present.
     */
    private static final String MINIMUM_MAVEN_VERSION = "3.0.2";
    private final ServerDetails details;
    private final Credentials overridingResolverCredentials;

    @DataBoundConstructor
    public ArtifactoryMaven3NativeConfigurator(ServerDetails details, Credentials overridingResolverCredentials) {
        this.details = details;
        this.overridingResolverCredentials = overridingResolverCredentials;
    }

    public ServerDetails getDetails() {
        return details;
    }

    public String getDownloadRepositoryKey() {
        return details != null ? details.downloadRepositoryKey : null;
    }

    public String getArtifactoryName() {
        return details != null ? details.artifactoryName : null;
    }

    public String getRepositoryKey() {
        return details != null ? details.repositoryKey : null;
    }

    @Override
    public Collection<? extends Action> getProjectActions(AbstractProject project) {
        return Collections.emptyList();
    }

    public boolean isOverridingDefaultResolver() {
        return getOverridingResolverCredentials() != null;
    }

    public Credentials getOverridingResolverCredentials() {
        return overridingResolverCredentials;
    }

    @Override
    public Environment setUp(final AbstractBuild build, Launcher launcher, BuildListener listener)
            throws IOException, InterruptedException {
        final MavenModuleSet project = (MavenModuleSet) build.getProject();
        EnvVars envVars = build.getEnvironment(listener);
        // get the maven installation
        Maven.MavenInstallation mavenInstallation = getMavenInstallation(project, envVars, listener);
        MavenInformation information = build.getWorkspace().act(new MavenVersionCallable(mavenInstallation.getHome()));
        // if the installation is not the minimal required version do nothing.
        if (!(isValidMavenVersion(information.getVersion()))) {
            return new Environment() {
                // return the empty environment
            };
        }
        final String mavenOpts = project.getMavenOpts();
        try {
            project.setMavenOpts(appendNewMavenOpts(project, build));
        } catch (IOException e) {
            throw new RuntimeException("Unable to manipulate maven_opts for project: " + project, e);
        }
        final File classWorldsFile = File.createTempFile("classworlds", "conf");
        URL resource = getClass().getClassLoader().getResource("org/jfrog/hudson/maven3/classworlds-native.conf");
        final String classworldsConfPath = ExtractorUtils.copyClassWorldsFile(build, resource, classWorldsFile);
        build.setResult(Result.SUCCESS);
        return new Environment() {
            @Override
            public void buildEnvVars(Map<String, String> env) {
                super.buildEnvVars(env);
                final ArtifactoryServer artifactoryServer = getArtifactoryServer();
                Credentials preferredResolver = CredentialResolver
                        .getPreferredResolver(ArtifactoryMaven3NativeConfigurator.this, artifactoryServer);

                ArtifactoryClientConfiguration configuration = new ArtifactoryClientConfiguration(new NullLog());
                configuration.setContextUrl(artifactoryServer.getUrl());
                configuration.resolver.setRepoKey(getDownloadRepositoryKey());
                configuration.resolver.setUsername(preferredResolver.getUsername());
                configuration.resolver.setPassword(<PASSWORD>());
                ExtractorUtils.addBuildRootIfNeeded(build, configuration);
                env.putAll(configuration.getAllProperties());
                ExtractorUtils.addCustomClassworlds(env, classworldsConfPath);
            }

            @Override
            public boolean tearDown(AbstractBuild build, BuildListener listener)
                    throws IOException, InterruptedException {
                final MavenModuleSet project = (MavenModuleSet) build.getProject();
                project.setMavenOpts(mavenOpts);
                FileUtils.deleteQuietly(classWorldsFile);
                return super.tearDown(build, listener);
            }
        };
    }


    private boolean isValidMavenVersion(String version) {
        String[] versionSplit = StringUtils.split(version, ".");
        if (Integer.parseInt(versionSplit[0]) == 2) {
            return false;
        }
        if (versionSplit.length == 3) {
            if (Integer.parseInt(versionSplit[2]) < 2) {
                return false;
            }
        }
        return true;
    }

    /**
     * Get the {@link hudson.model.EnvironmentSpecific} and {@link hudson.slaves.NodeSpecific} Maven installation. First
     * get the descriptor from the global Jenkins. Then populate it accordingly from the specific environment node that
     * the process is currently running in e.g. the MAVEN_HOME variable may be defined only in the remote node and
     * Jenkins is not persisting it as part of its installations.
     *
     * @param project  The Maven project that the maven installation is taken from.
     * @param vars     The build's environment variables.
     * @param listener The build's event listener
     * @throws AbortException If the {@link Maven.MavenInstallation} that is taken from the project is {@code null} then
     *                        this exception is thrown.
     */
    private Maven.MavenInstallation getMavenInstallation(MavenModuleSet project, EnvVars vars, BuildListener listener)
            throws IOException, InterruptedException {
        Maven.MavenInstallation mavenInstallation = project.getMaven();
        if (mavenInstallation == null) {
            throw new AbortException("A Maven installation needs to be available for this project to be built.\n" +
                    "Either your server has no Maven installations defined, or the requested Maven version does not exist.");
        }
        return mavenInstallation.forEnvironment(vars).forNode(Computer.currentComputer().getNode(), listener);
    }
{'fraction_non_alphanumeric': 0.07892191630666065, 'fraction_numerical': 0.0015474885550325617, 'mean_word_length': 3.2563117453347967, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3875727', 'n_tokens_mistral': 4140, 'n_tokens_neox': 3955, 'n_words': 986}