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

hudson.maven.MavenUtil Maven / Gradle / Ivy

package hudson.maven;

import hudson.AbortException;
import hudson.model.BuildListener;
import hudson.model.TaskListener;
import hudson.model.AbstractProject;
import hudson.tasks.Maven.MavenInstallation;
import hudson.tasks.Maven.ProjectWithMaven;
import org.apache.maven.embedder.MavenEmbedderException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

/**
 * @author Kohsuke Kawaguchi
 */
public class MavenUtil {
    /**
     * @deprecated
     *      Use {@link MavenInstallation#createEmbedder(BuildListener, String)}
     *      or other overloaded versions that infers maven home.
     */
    public static MavenEmbedder createEmbedder(TaskListener listener, String profiles) throws MavenEmbedderException, IOException {
        return createEmbedder(listener,(File)null,profiles);
    }

    /**
     * This version tries to infer mavenHome by looking at a project.
     *
     * @see #createEmbedder(TaskListener, File, String)
     */
    public static MavenEmbedder createEmbedder(TaskListener listener, AbstractProject project, String profiles) throws MavenEmbedderException, IOException {
        MavenInstallation m=null;
        if (project instanceof ProjectWithMaven)
            m = ((ProjectWithMaven) project).inferMavenInstallation();

        return createEmbedder(listener,m!=null?m.getHomeDir():null,profiles);
    }

    /**
     * Creates a fresh {@link MavenEmbedder} instance.
     *
     * @param listener
     *      This is where the log messages from Maven will be recorded.
     * @param mavenHome
     *      Directory of the Maven installation. We read {@code conf/settings.xml}
     *      from here. Can be null.
     * @param profiles
     *      Profiles to activate/deactivate. Can be null.
     */
    public static MavenEmbedder createEmbedder(TaskListener listener, File mavenHome, String profiles) throws MavenEmbedderException, IOException {
        MavenEmbedder maven = new MavenEmbedder(mavenHome);

        ClassLoader cl = MavenUtil.class.getClassLoader();
        maven.setClassLoader(new MaskingClassLoader(cl));
        maven.setLogger( new EmbedderLoggerImpl(listener) );

        // make sure ~/.m2 exists to avoid http://www.nabble.com/BUG-Report-tf3401736.html
        File m2Home = new File(MavenEmbedder.userHome, ".m2");
        m2Home.mkdirs();
        if(!m2Home.exists()) {
            listener.getLogger().println("Failed to create "+m2Home+
                "\nSee https://hudson.dev.java.net/cannot-create-.m2.html");
            throw new AbortException();
        }

        maven.setProfiles(profiles);
        maven.start();

        return maven;
    }


    /**
     * Recursively resolves module POMs that are referenced from
     * the given {@link MavenProject} and parses them into
     * {@link MavenProject}s.
     *
     * @param rel
     *      Used to compute the relative path. Pass in "" to begin.
     * @param relativePathInfo
     *      Upon the completion of this method, this variable stores the relative path
     *      from the root directory of the given {@link MavenProject} to the root directory
     *      of each of the newly parsed {@link MavenProject}.
     *
     * @throws AbortException
     *      errors will be reported to the listener and the exception thrown.
     */
    public static void resolveModules(MavenEmbedder embedder, MavenProject project, String rel, Map relativePathInfo, BuildListener listener) throws ProjectBuildingException, AbortException {

        File basedir = project.getFile().getParentFile();
        relativePathInfo.put(project,rel);

        List modules = new ArrayList();

        for (String modulePath : (List) project.getModules()) {
            File moduleFile = new File(new File(basedir, modulePath),"pom.xml");
            if(!moduleFile.exists()) {
                listener.getLogger().println(moduleFile+" is referenced from "+project.getFile()+" but it doesn't exist");
                throw new AbortException();
            }

            String relativePath = rel;
            if(relativePath.length()>0) relativePath+='/';
            relativePath+=modulePath;

            MavenProject child = embedder.readProject(moduleFile);
            resolveModules(embedder,child,relativePath,relativePathInfo,listener);
            modules.add(child);
        }

        project.setCollectedProjects(modules);
    }

    /**
     * When we run in Jetty during development, embedded Maven will end up
     * seeing some of the Maven class visible through Jetty, and this confuses it.
     *
     * 

* Specifically, embedded Maven will find all the component descriptors * visible through Jetty, yet when it comes to loading classes, classworlds * still load classes from local realms created inside embedder. * *

* This classloader prevents this issue by hiding the component descriptor * visible through Jetty. */ private static final class MaskingClassLoader extends ClassLoader { public MaskingClassLoader(ClassLoader parent) { super(parent); } public Enumeration getResources(String name) throws IOException { final Enumeration e = super.getResources(name); return new Enumeration() { URL next; public boolean hasMoreElements() { fetch(); return next!=null; } public URL nextElement() { fetch(); URL r = next; next = null; return r; } private void fetch() { while(next==null && e.hasMoreElements()) { next = e.nextElement(); if(next.toExternalForm().contains("maven-plugin-tools-api")) next = null; } } }; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy