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

hudson.maven.MavenModuleSet Maven / Gradle / Ivy

package hudson.maven;

import hudson.*;
import hudson.model.*;
import hudson.model.Descriptor.FormException;
import static hudson.model.ItemGroupMixIn.loadChildren;
import hudson.model.Queue;
import hudson.model.Queue.Task;
import hudson.search.CollectionSearchIndex;
import hudson.search.SearchIndexBuilder;
import hudson.tasks.Maven.MavenInstallation;
import hudson.tasks.*;
import hudson.util.CopyOnWriteMap;
import hudson.util.DescribableList;
import hudson.util.FormFieldValidator;
import hudson.util.Function1;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.util.*;

import net.sf.json.JSONObject;

/**
 * Group of {@link MavenModule}s.
 *
 * 

* This corresponds to the group of Maven POMs that constitute a single * tree of projects. This group serves as the grouping of those related * modules. * * @author Kohsuke Kawaguchi */ public final class MavenModuleSet extends AbstractMavenProject implements TopLevelItem, ItemGroup, SCMedItem, DescribableList.Owner { /** * All {@link MavenModule}s, keyed by their {@link MavenModule#getModuleName()} module name}s. */ transient /*final*/ Map modules = new CopyOnWriteMap.Tree(); /** * Topologically sorted list of modules. This only includes live modules, * since archived ones usually don't have consistent history. */ @CopyOnWrite transient List sortedActiveModules; /** * Name of the top-level module. Null until the root module is determined. */ private ModuleName rootModule; private String rootPOM; private String goals; /** * Default goals specified in POM. Can be null. */ private String defaultGoals; /** * Identifies {@link MavenInstallation} to be used. * Null to indicate 'default' maven. */ private String mavenName; /** * Equivalent of CLI MAVEN_OPTS. Can be null. */ private String mavenOpts; /** * If true, the build will be aggregator style, meaning * all the modules are executed in a single Maven invocation, as in CLI. * False otherwise, meaning each module is built separately and possibly in parallel. * * @since 1.133 */ private boolean aggregatorStyleBuild = true; /** * If true, the build will use its own local Maven repository * via "-Dmaven.repo.local=...". *

* This would consume additional disk space, but provides isolation with other builds on the same machine, * such as mixing SNAPSHOTS. Maven also doesn't try to coordinate the concurrent access to Maven repositories * from multiple Maven process, so this helps there too. * * @since 1.223 */ private boolean usePrivateRepository = false; /** * Reporters configured at {@link MavenModuleSet} level. Applies to all {@link MavenModule} builds. */ private DescribableList> reporters = new DescribableList>(this); /** * List of active {@link Publisher}s configured for this project. * @since 1.176 */ private DescribableList> publishers = new DescribableList>(this); /** * List of active ${link BuildWrapper}s configured for this project. * @since 1.212 */ private DescribableList> buildWrappers = new DescribableList>(this); public MavenModuleSet(String name) { super(Hudson.getInstance(),name); } public String getUrlChildPrefix() { // seemingly redundant "./" is used to make sure that ':' is not interpreted as the scheme identifier return "."; } public Hudson getParent() { return Hudson.getInstance(); } public Collection getItems() { return modules.values(); } public Collection getModules() { return getItems(); } public MavenModule getItem(String name) { return modules.get(ModuleName.fromString(name)); } public MavenModule getModule(String name) { return getItem(name); } protected void updateTransientActions() { super.updateTransientActions(); // Fix for ISSUE-1149 for (MavenModule module: modules.values()) { module.updateTransientActions(); } if(publishers!=null) // this method can be loaded from within the onLoad method, where this might be null for (BuildStep step : publishers) { Action a = step.getProjectAction(this); if(a!=null) transientActions.add(a); } } protected void addTransientActionsFromBuild(MavenModuleSetBuild build, Set added) { if(build==null) return; for (Action a : build.getActions()) if(a instanceof MavenAggregatedReport) if(added.add(a.getClass())) transientActions.add(((MavenAggregatedReport)a).getProjectAction(this)); List list = build.projectActionReporters; if(list==null) return; for (MavenReporter step : list) { if(!added.add(step.getClass())) continue; // already added Action a = step.getAggregatedProjectAction(this); if(a!=null) transientActions.add(a); } } /** * Called by {@link MavenModule#doDoDelete(StaplerRequest, StaplerResponse)}. * Real deletion is done by the caller, and this method only adjusts the * data structure the parent maintains. */ /*package*/ void onModuleDeleted(MavenModule module) { modules.remove(module.getModuleName()); } /** * Returns true if there's any disabled module. */ public boolean hasDisabledModule() { for (MavenModule m : modules.values()) { if(m.isDisabled()) return true; } return false; } /** * Possibly empty list of all disabled modules (if disabled==true) * or all enabeld modules (if disabled==false) */ public List getDisabledModules(boolean disabled) { if(!disabled && sortedActiveModules!=null) return sortedActiveModules; List r = new ArrayList(); for (MavenModule m : modules.values()) { if(m.isDisabled()==disabled) r.add(m); } return r; } public Indenter createIndenter() { return new Indenter() { protected int getNestLevel(MavenModule job) { return job.nestLevel; } }; } public boolean isAggregatorStyleBuild() { return aggregatorStyleBuild; } public boolean usesPrivateRepository() { return usePrivateRepository; } /** * List of active {@link MavenReporter}s that should be applied to all module builds. */ public DescribableList> getReporters() { return reporters; } /** * List of active {@link Publisher}s. Can be empty but never null. */ public DescribableList> getPublishers() { return publishers; } @Override public DescribableList> getPublishersList() { return publishers; } /** * List of active {@link BuildWrapper}s. Can be empty but never null. */ public DescribableList> getBuildWrappers() { return buildWrappers; } public Object getDynamic(String token, StaplerRequest req, StaplerResponse rsp) { if(ModuleName.isValid(token)) return getModule(token); return super.getDynamic(token,req,rsp); } public File getRootDirFor(MavenModule child) { return new File(getModulesDir(),child.getModuleName().toFileSystemName()); } public Collection getAllJobs() { Set jobs = new HashSet(getItems()); jobs.add(this); return jobs; } /** * Gets the workspace of this job. */ public FilePath getWorkspace() { Node node = getLastBuiltOn(); if(node==null) node = Hudson.getInstance(); return node.getWorkspaceFor(this); } @Override protected Class getBuildClass() { return MavenModuleSetBuild.class; } @Override protected SearchIndexBuilder makeSearchIndex() { return super.makeSearchIndex() .add(new CollectionSearchIndex() {// for computers protected MavenModule get(String key) { for (MavenModule m : modules.values()) { if(m.getDisplayName().equals(key)) return m; } return null; } protected Collection all() { return modules.values(); } protected String getName(MavenModule o) { return o.getName(); } }); } @Override public boolean isFingerprintConfigured() { return true; } public void onLoad(ItemGroup parent, String name) throws IOException { modules = Collections.emptyMap(); // needed during load super.onLoad(parent, name); modules = loadChildren(this, getModulesDir(),new Function1() { public ModuleName call(MavenModule module) { return module.getModuleName(); } }); // update the transient nest level field. MavenModule root = getRootModule(); if(root!=null && root.getChildren()!=null) { List sortedList = new ArrayList(); Stack q = new Stack(); root.nestLevel = 0; q.push(root); while(!q.isEmpty()) { MavenModule p = q.pop(); sortedList.add(p); List children = p.getChildren(); if(children!=null) { for (MavenModule m : children) m.nestLevel = p.nestLevel+1; for( int i=children.size()-1; i>=0; i--) // add them in the reverse order q.push(children.get(i)); } } this.sortedActiveModules = sortedList; } else { this.sortedActiveModules = getDisabledModules(false); } if(reporters==null) reporters = new DescribableList>(this); reporters.setOwner(this); if(publishers==null) publishers = new DescribableList>(this); publishers.setOwner(this); if(buildWrappers==null) buildWrappers = new DescribableList>(this); buildWrappers.setOwner(this); updateTransientActions(); } private File getModulesDir() { return new File(getRootDir(),"modules"); } /** * To make it easy to grasp relationship among modules * and the module set, we'll align the build numbers of * all the modules. * *

* This method is invoked from {@link Executor#run()}, * and because of the mutual exclusion among {@link MavenModuleSetBuild} * and {@link MavenBuild}, we can safely touch all the modules. */ public synchronized int assignBuildNumber() throws IOException { // determine the next value updateNextBuildNumber(); return super.assignBuildNumber(); } public void logRotate() throws IOException { super.logRotate(); // perform the log rotation of modules for (MavenModule m : modules.values()) m.logRotate(); } /** * The next build of {@link MavenModuleSet} must have * the build number newer than any of the current module build. */ /*package*/ void updateNextBuildNumber() throws IOException { int next = this.nextBuildNumber; for (MavenModule m : modules.values()) next = Math.max(next,m.getNextBuildNumber()); if(this.nextBuildNumber!=next) { this.nextBuildNumber=next; this.saveNextBuildNumber(); } } protected void buildDependencyGraph(DependencyGraph graph) { publishers.buildDependencyGraph(this,graph); buildWrappers.buildDependencyGraph(this,graph); } public MavenModule getRootModule() { if(rootModule==null) return null; return modules.get(rootModule); } @Override public MavenInstallation inferMavenInstallation() { return getMaven(); } @Override protected Set getResourceActivities() { final Set activities = new HashSet(); activities.addAll(super.getResourceActivities()); activities.addAll(Util.filter(publishers,ResourceActivity.class)); activities.addAll(Util.filter(buildWrappers,ResourceActivity.class)); return activities; } /** * Gets the location of top-level pom.xml relative to the workspace root. */ public String getRootPOM() { if(rootPOM==null) return "pom.xml"; return rootPOM; } public AbstractProject asProject() { return this; } /** * Gets the list of goals to execute. */ public String getGoals() { if(goals==null) { if(defaultGoals!=null) return defaultGoals; return "install"; } return goals; } /** * If the list of configured goals contain the "-P" option, * return the configured profiles. Otherwise null. */ public String getProfiles() { boolean switchFound=false; for (String t : Util.tokenize(getGoals())) { if(switchFound) return t; if(t.equals("-P")) switchFound=true; } return null; } /** * Possibly null, whitespace-separated (including TAB, NL, etc) VM options * to be used to launch Maven process. */ public String getMavenOpts() { return mavenOpts; } /** * Gets the Maven to invoke. * If null, we pick any random Maven installation. */ public MavenInstallation getMaven() { for( MavenInstallation i : DESCRIPTOR.getMavenDescriptor().getInstallations() ) { if(mavenName==null || i.getName().equals(mavenName)) return i; } return null; } /** * Returns the {@link MavenModule}s that are in the queue. */ public List getQueueItems() { List r = new ArrayList(); for( Queue.Item item : Hudson.getInstance().getQueue().getItems() ) { Task t = item.task; if((t instanceof MavenModule && ((MavenModule)t).getParent()==this) || t ==this) r.add(item); } return r; } /** * Gets the list of goals specified by the user, * without taking inheritance and POM default goals * into account. * *

* This is only used to present the UI screen, and in * all the other cases {@link #getGoals()} should be used. */ public String getUserConfiguredGoals() { return goals; } /*package*/ void reconfigure(PomInfo rootPom) throws IOException { if(this.rootModule!=null && this.rootModule.equals(rootPom.name)) return; // no change this.rootModule = rootPom.name; this.defaultGoals = rootPom.defaultGoal; save(); } // // // Web methods // // protected void submit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { super.submit(req,rsp); rootPOM = Util.fixEmpty(req.getParameter("rootPOM").trim()); if(rootPOM!=null && rootPOM.equals("pom.xml")) rootPOM=null; // normalization goals = Util.fixEmpty(req.getParameter("goals").trim()); mavenOpts = Util.fixEmpty(req.getParameter("mavenOpts").trim()); mavenName = req.getParameter("maven_version"); aggregatorStyleBuild = !req.hasParameter("maven.perModuleBuild"); usePrivateRepository = req.hasParameter("maven.usePrivateRepository"); JSONObject json = req.getSubmittedForm(); reporters.rebuild(req,json,MavenReporters.getConfigurableList(),"reporter"); publishers.rebuild(req,json,BuildStepDescriptor.filter(BuildStep.PUBLISHERS,this.getClass()),"publisher"); buildWrappers.rebuild(req,json,BuildWrappers.getFor(this),"wrapper"); updateTransientActions(); // to pick up transient actions from builder, publisher, etc. } /** * Delete all disabled modules. */ public void doDoDeleteAllDisabledModules(StaplerRequest req, StaplerResponse rsp) throws IOException { checkPermission(DELETE); for( MavenModule m : getDisabledModules(true)) m.delete(); rsp.sendRedirect2("."); } /** * Check the location of POM. */ public void doCheckRootPOM(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { new FormFieldValidator.WorkspaceFilePath(req,rsp,true,true) { protected AbstractProject getProject() { return MavenModuleSet.this; } protected FilePath getBaseDirectory(AbstractProject p) { return p.getModuleRoot(); } }.process(); } public TopLevelItemDescriptor getDescriptor() { return DESCRIPTOR; } public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); public static final class DescriptorImpl extends TopLevelItemDescriptor { private DescriptorImpl() { super(MavenModuleSet.class); } public String getDisplayName() { return Messages.MavenModuleSet_DiplayName(); } public MavenModuleSet newInstance(String name) { return new MavenModuleSet(name); } public Maven.DescriptorImpl getMavenDescriptor() { return Maven.DESCRIPTOR; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy