<commit_before>package hudson.tasks;

import hudson.CopyOnWrite;
import hudson.FilePath.FileCallable;
import hudson.Functions;
import hudson.Launcher;
import hudson.Launcher.LocalLauncher;
import hudson.Util;
import hudson.EnvVars;
import hudson.maven.MavenEmbedder;
import hudson.maven.MavenUtil;
import hudson.maven.RedeployPublisher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.ParametersAction;
import hudson.remoting.Callable;
import hudson.remoting.VirtualChannel;
import hudson.util.ArgumentListBuilder;
import hudson.util.FormFieldValidator;
import hudson.util.NullStream;
import hudson.util.StreamTaskListener;
import hudson.util.VariableResolver;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.DataBoundConstructor;
import org.apache.maven.embedder.MavenEmbedderException;

import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Properties;

import net.sf.json.JSONObject;

/**
 * Build by using Maven.
 *
 * @author <NAME>
 */
public class Maven extends Builder {
    /**
     * The targets and other maven options.
     * Can be separated by SP or NL.
     */
    public final String targets;

    /**
     * Identifies {@link MavenInstallation} to be used.
     */
    public final String mavenName;

    /**
     * MAVEN_OPTS if not null.
     */
    public final String jvmOptions;

    /**
     * Optional POM file path relative to the workspace.
     * Used for the Maven '-f' option.
     */
    public final String pom;

    /**
     * Optional properties to be passed to Maven. Follows {@link Properties} syntax.
     */
    public final String properties;

    private final static String MAVEN_1_INSTALLATION_COMMON_FILE = "bin/maven";
    private final static String MAVEN_2_INSTALLATION_COMMON_FILE = "bin/mvn";

    public Maven(String targets,String name) {
        this(targets,name,null,null,null);
    }

    @DataBoundConstructor
    public Maven(String targets,String name, String pom, String properties, String jvmOptions) {
        this.targets = targets;
        this.mavenName = name;
        this.pom = Util.fixEmptyAndTrim(pom);
        this.properties = Util.fixEmptyAndTrim(properties);
        this.jvmOptions = Util.fixEmptyAndTrim(jvmOptions);
    }

    public String getTargets() {
        return targets;
    }

    /**
     * Gets the Maven to invoke,
     * or null to invoke the default one.
     */
    public MavenInstallation getMaven() {
        for( MavenInstallation i : DESCRIPTOR.getInstallations() ) {
            if(mavenName !=null && i.getName().equals(mavenName))
                return i;
        }
        return null;
    }

    /**
     * Looks for <tt>pom.xlm</tt> or <tt>project.xml</tt> to determine the maven executable
     * name.
     */
    private static final class DecideDefaultMavenCommand implements FileCallable<String> {
        // command line arguments.
        private final String arguments;

        public DecideDefaultMavenCommand(String arguments) {
            this.arguments = arguments;
        }

        public String invoke(File ws, VirtualChannel channel) throws IOException {
            String seed=null;

            // check for the -f option
            StringTokenizer tokens = new StringTokenizer(arguments);
            while(tokens.hasMoreTokens()) {
                String t = tokens.nextToken();
                if(t.equals("-f") && tokens.hasMoreTokens()) {
                    File file = new File(ws,tokens.nextToken());
                    if(!file.exists())
                        continue;   // looks like an error, but let the execution fail later
                    if(file.isDirectory())
                        // in M1, you specify a directory in -f
                        seed = "maven";
                    else
                        // in M2, you specify a POM file name.
                        seed = "mvn";
                    break;
                }
            }

            if(seed==null) {
                // as of 1.212 (2008 April), I think Maven2 mostly replaced Maven1, so
                // switching to err on M2 side.
                if(new File(ws,"project.xml").exists())
                    seed = "maven";
                else
                    seed = "mvn";
            }

            if(Functions.isWindows())
                seed += ".bat";
            return seed;
        }
    }

    public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
        AbstractProject proj = build.getProject();

        VariableResolver<String> vr = build.getBuildVariableResolver();
        ParametersAction parameters = build.getAction(ParametersAction.class);
        if(parameters!=null)
            vr = parameters.createVariableResolver(build);

        String targets = Util.replaceMacro(this.targets,vr);

        int startIndex = 0;
        int endIndex;
        do {
            // split targets into multiple invokations of maven separated by |
            endIndex = targets.indexOf('|', startIndex);
            if (-1 == endIndex) {
                endIndex = targets.length();
            }

            Map<String,String> env = build.getEnvVars();

            String normalizedTarget = targets
                    .substring(startIndex, endIndex)
                    .replaceAll("[\t\r\n]+"," ");
            normalizedTarget = Util.replaceMacro(normalizedTarget,env);

            ArgumentListBuilder args = new ArgumentListBuilder();
            MavenInstallation ai = getMaven();
            if(ai==null) {
                String execName = proj.getWorkspace().act(new DecideDefaultMavenCommand(normalizedTarget));
                args.add(execName);
            } else {
                String exec = ai.getExecutable(launcher);
                if(exec==null) {
                    listener.fatalError(Messages.Maven_NoExecutable(ai.getMavenHome()));
                    return false;
                }
                args.add(exec);
            }
            args.addKeyValuePairs("-D",build.getBuildVariables());
            args.addKeyValuePairsFromPropertyString("-D",properties,vr);
            args.addTokenized(normalizedTarget);

            if(ai!=null) {
                // if somebody has use M2_HOME they will get a classloading error
                // when M2_HOME points to a different version of Maven2 from
                // MAVEN_HOME (as Maven 2 gives M2_HOME priority.)
                // 
                // The other solution would be to set M2_HOME if we are calling Maven2 
                // and MAVEN_HOME for Maven1 (only of use for strange people that
                // are calling Maven2 from Maven1)
                env.put("M2_HOME",ai.getMavenHome());
                env.put("MAVEN_HOME",ai.getMavenHome());
            }
            // just as a precaution
            // see http://maven.apache.org/continuum/faqs.html#how-does-continuum-detect-a-successful-build
            env.put("MAVEN_TERMINATE_CMD","on");

            if(jvmOptions!=null)
                env.put("MAVEN_OPTS",jvmOptions);<commit_msg>forgot to handle the -f option<commit_after>package hudson.tasks;

import hudson.CopyOnWrite;
import hudson.FilePath.FileCallable;
import hudson.Functions;
import hudson.Launcher;
import hudson.Launcher.LocalLauncher;
import hudson.Util;
import hudson.EnvVars;
import hudson.maven.MavenEmbedder;
import hudson.maven.MavenUtil;
import hudson.maven.RedeployPublisher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.ParametersAction;
import hudson.remoting.Callable;
import hudson.remoting.VirtualChannel;
import hudson.util.ArgumentListBuilder;
import hudson.util.FormFieldValidator;
import hudson.util.NullStream;
import hudson.util.StreamTaskListener;
import hudson.util.VariableResolver;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.DataBoundConstructor;
import org.apache.maven.embedder.MavenEmbedderException;

import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Properties;

import net.sf.json.JSONObject;

/**
 * Build by using Maven.
 *
 * @author <NAME>
 */
public class Maven extends Builder {
    /**
     * The targets and other maven options.
     * Can be separated by SP or NL.
     */
    public final String targets;

    /**
     * Identifies {@link MavenInstallation} to be used.
     */
    public final String mavenName;

    /**
     * MAVEN_OPTS if not null.
     */
    public final String jvmOptions;

    /**
     * Optional POM file path relative to the workspace.
     * Used for the Maven '-f' option.
     */
    public final String pom;

    /**
     * Optional properties to be passed to Maven. Follows {@link Properties} syntax.
     */
    public final String properties;

    private final static String MAVEN_1_INSTALLATION_COMMON_FILE = "bin/maven";
    private final static String MAVEN_2_INSTALLATION_COMMON_FILE = "bin/mvn";

    public Maven(String targets,String name) {
        this(targets,name,null,null,null);
    }

    @DataBoundConstructor
    public Maven(String targets,String name, String pom, String properties, String jvmOptions) {
        this.targets = targets;
        this.mavenName = name;
        this.pom = Util.fixEmptyAndTrim(pom);
        this.properties = Util.fixEmptyAndTrim(properties);
        this.jvmOptions = Util.fixEmptyAndTrim(jvmOptions);
    }

    public String getTargets() {
        return targets;
    }

    /**
     * Gets the Maven to invoke,
     * or null to invoke the default one.
     */
    public MavenInstallation getMaven() {
        for( MavenInstallation i : DESCRIPTOR.getInstallations() ) {
            if(mavenName !=null && i.getName().equals(mavenName))
                return i;
        }
        return null;
    }

    /**
     * Looks for <tt>pom.xlm</tt> or <tt>project.xml</tt> to determine the maven executable
     * name.
     */
    private static final class DecideDefaultMavenCommand implements FileCallable<String> {
        // command line arguments.
        private final String arguments;

        public DecideDefaultMavenCommand(String arguments) {
            this.arguments = arguments;
        }

        public String invoke(File ws, VirtualChannel channel) throws IOException {
            String seed=null;

            // check for the -f option
            StringTokenizer tokens = new StringTokenizer(arguments);
            while(tokens.hasMoreTokens()) {
                String t = tokens.nextToken();
                if(t.equals("-f") && tokens.hasMoreTokens()) {
                    File file = new File(ws,tokens.nextToken());
                    if(!file.exists())
                        continue;   // looks like an error, but let the execution fail later
                    if(file.isDirectory())
                        // in M1, you specify a directory in -f
                        seed = "maven";
                    else
                        // in M2, you specify a POM file name.
                        seed = "mvn";
                    break;
                }
            }

            if(seed==null) {
                // as of 1.212 (2008 April), I think Maven2 mostly replaced Maven1, so
                // switching to err on M2 side.
                if(new File(ws,"project.xml").exists())
                    seed = "maven";
                else
                    seed = "mvn";
            }

            if(Functions.isWindows())
                seed += ".bat";
            return seed;
        }
    }

    public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
        AbstractProject proj = build.getProject();

        VariableResolver<String> vr = build.getBuildVariableResolver();
        ParametersAction parameters = build.getAction(ParametersAction.class);
        if(parameters!=null)
            vr = parameters.createVariableResolver(build);

        String targets = Util.replaceMacro(this.targets,vr);

        int startIndex = 0;
        int endIndex;
        do {
            // split targets into multiple invokations of maven separated by |
            endIndex = targets.indexOf('|', startIndex);
            if (-1 == endIndex) {
                endIndex = targets.length();
            }

            Map<String,String> env = build.getEnvVars();

            String normalizedTarget = targets
                    .substring(startIndex, endIndex)
                    .replaceAll("[\t\r\n]+"," ");
            normalizedTarget = Util.replaceMacro(normalizedTarget,env);

            ArgumentListBuilder args = new ArgumentListBuilder();
            MavenInstallation ai = getMaven();
            if(ai==null) {
                String execName = proj.getWorkspace().act(new DecideDefaultMavenCommand(normalizedTarget));
                args.add(execName);
            } else {
                String exec = ai.getExecutable(launcher);
                if(exec==null) {
                    listener.fatalError(Messages.Maven_NoExecutable(ai.getMavenHome()));
                    return false;
                }
                args.add(exec);
            }
            if(pom!=null)
                args.add("-f",pom);
            args.addKeyValuePairs("-D",build.getBuildVariables());
            args.addKeyValuePairsFromPropertyString("-D",properties,vr);
            args.addTokenized(normalizedTarget);

            if(ai!=null) {
                // if somebody has use M2_HOME they will get a classloading error
                // when M2_HOME points to a different version of Maven2 from
                // MAVEN_HOME (as Maven 2 gives M2_HOME priority.)
                // 
                // The other solution would be to set M2_HOME if we are calling Maven2 
                // and MAVEN_HOME for Maven1 (only of use for strange people that
                // are calling Maven2 from Maven1)
                env.put("M2_HOME",ai.getMavenHome());
                env.put("MAVEN_HOME",ai.getMavenHome());
            }
            // just as a precaution
            // see http://maven.apache.org/continuum/faqs.html#how-does-continuum-detect-a-successful-build
            env.put("MAVEN_TERMINATE_CMD","on");

            if(jvmOptions!=null)
                env.put("MAVEN_OPTS",jvmOptions);
{'fraction_non_alphanumeric': 0.09555510725573263, 'fraction_numerical': 0.0037657185125411874, 'mean_word_length': 2.0619724109532633, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7475519', 'n_tokens_mistral': 4191, 'n_tokens_neox': 3932, 'n_words': 1000}