Java tutorial
/* * The MIT License * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Jorg Heymans, Peter Hayes, Red Hat, Inc., Stephen Connolly, id:cactusman * Olivier Lamy * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package hudson.gridmaven; import static hudson.Util.*; import static hudson.model.ItemGroupMixIn.loadChildren; import hudson.CopyOnWrite; import hudson.EnvVars; import hudson.Extension; import hudson.FilePath; import hudson.Functions; import hudson.Indenter; import hudson.Util; import hudson.gridmaven.Messages; import hudson.gridmaven.local_repo.DefaultLocalRepositoryLocator; import hudson.gridmaven.local_repo.LocalRepositoryLocator; import hudson.gridmaven.local_repo.PerJobLocalRepositoryLocator; import hudson.gridmaven.settings.SettingConfig; import hudson.gridmaven.settings.SettingsProviderUtils; import hudson.model.AbstractProject; import hudson.model.Action; import hudson.model.BuildableItemWithBuildWrappers; import hudson.model.DependencyGraph; import hudson.model.Descriptor; import hudson.model.Descriptor.FormException; import hudson.model.Executor; import hudson.model.Item; import hudson.model.ItemGroup; import hudson.model.Job; import hudson.model.Queue; import hudson.model.Queue.Task; import hudson.model.ResourceActivity; import hudson.model.Result; import hudson.model.SCMedItem; import hudson.model.Saveable; import hudson.model.TaskListener; import hudson.model.TopLevelItem; import hudson.search.CollectionSearchIndex; import hudson.search.SearchIndexBuilder; import hudson.tasks.BuildStep; import hudson.tasks.BuildWrapper; import hudson.tasks.BuildWrappers; import hudson.tasks.Builder; import hudson.tasks.Fingerprinter; import hudson.tasks.Mailer; import hudson.tasks.Maven; import hudson.tasks.Maven.MavenInstallation; import hudson.tasks.Publisher; import hudson.tasks.JavadocArchiver; import hudson.tasks.junit.JUnitResultArchiver; import hudson.util.CopyOnWriteMap; import hudson.util.DescribableList; import hudson.util.FormValidation; import hudson.util.Function1; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.Stack; import javax.servlet.ServletException; import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.apache.commons.lang.math.NumberUtils; import org.apache.maven.model.building.ModelBuildingRequest; import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.HttpResponses; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.export.Exported; /** * Group of {@link MavenModule}s. * * <p> * 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 class MavenModuleSet extends AbstractMavenProject<MavenModuleSet, MavenModuleSetBuild> implements TopLevelItem, ItemGroup<MavenModule>, SCMedItem, Saveable, BuildableItemWithBuildWrappers { /** * All {@link MavenModule}s, keyed by their {@link MavenModule#getModuleName()} module name}s. */ transient /*final*/ Map<ModuleName, MavenModule> modules = new CopyOnWriteMap.Tree<ModuleName, MavenModule>(); /** * Topologically sorted list of modules. This only includes live modules, * since archived ones usually don't have consistent history. */ @CopyOnWrite transient List<MavenModule> sortedActiveModules; /** * Name of the top-level module. Null until the root module is determined. */ private ModuleName rootModule; private String rootPOM; private String goals; private String alternateSettings; /** * 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 <tt>MAVEN_OPTS</tt>. 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, and if aggregatorStyleBuild is false and we are using Maven 2.1 or later, the build will * check the changeset before building, and if there are changes, only those modules which have changes * or those modules which failed or were unstable in the previous build will be built directly, using * Maven's make-like reactor mode. Any modules depending on the directly built modules will also be built, * but that's controlled by Maven. * * @since 1.318 */ private boolean incrementalBuild = false; /** * If true, the build will use its own local Maven repository * via "-Dmaven.repo.local=...". * <p> * 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 * @deprecated as of 1.448 * Subsumed by {@link #localRepository}. false maps to {@link DefaultLocalRepositoryLocator}, * and true maps to {@link PerJobLocalRepositoryLocator} */ private transient Boolean usePrivateRepository; /** * Encapsulates where to run the local repository. * * If null, inherited from the global configuration. * * @since 1.448 */ private LocalRepositoryLocator localRepository = null; /** * If true, the build will send a failure e-mail for each failing maven module. * Defaults to <code>true</code> to simulate old behavior. * <p> * see JENKINS-5695. */ private Boolean perModuleEmail = Boolean.TRUE; /** * If true, do not automatically schedule a build when one of the project dependencies is built. * <p> * See HUDSON-1714. */ private boolean ignoreUpstremChanges = false; /** * If true, do not archive artifacts to the master. */ private boolean archivingDisabled = false; /** * parameter for pom parsing by default <code>false</code> to be faster * @since 1.394 */ private boolean resolveDependencies = false; /** * parameter for pom parsing by default <code>false</code> to be faster * @since 1.394 */ private boolean processPlugins = false; /** * parameter for validation level during pom parsing by default the one corresponding * to the maven version used (2 or 3) * @since 1.394 */ private int mavenValidationLevel = -1; /** * Inform jenkins this build don't use UI code and can run without access to graphical environment. Could be used * later to select a headless-slave from a pool, but first introduced for JENKINS-9785 */ private boolean runHeadless = false; /** * @since 1.426 */ private String settingConfigId; /** * @since 1.426 */ private String globalSettingConfigId; /** * used temporary during maven build to store file path * @since 1.426 */ protected transient String globalSettingConfigPath; /** * Reporters configured at {@link MavenModuleSet} level. Applies to all {@link MavenModule} builds. */ private DescribableList<MavenReporter, Descriptor<MavenReporter>> reporters = new DescribableList<MavenReporter, Descriptor<MavenReporter>>( this); /** * List of active {@link Publisher}s configured for this project. * @since 1.176 */ private DescribableList<Publisher, Descriptor<Publisher>> publishers = new DescribableList<Publisher, Descriptor<Publisher>>( this); /** * List of active {@link BuildWrapper}s configured for this project. * @since 1.212 */ private DescribableList<BuildWrapper, Descriptor<BuildWrapper>> buildWrappers = new DescribableList<BuildWrapper, Descriptor<BuildWrapper>>( this); /** * List of active {@link Builder}s configured for this project. */ private DescribableList<Builder, Descriptor<Builder>> prebuilders = new DescribableList<Builder, Descriptor<Builder>>( this); private DescribableList<Builder, Descriptor<Builder>> postbuilders = new DescribableList<Builder, Descriptor<Builder>>( this); private Result runPostStepsIfResult; /** * @deprecated * Use {@link #MavenModuleSet(ItemGroup, String)} */ public MavenModuleSet(String name) { this(Jenkins.getInstance(), name); } public MavenModuleSet(ItemGroup parent, String name) { super(parent, name); } /** * Builders that are run before the main Maven execution. * * @since 1.433 */ public DescribableList<Builder, Descriptor<Builder>> getPrebuilders() { return prebuilders; } /** * Builders that are run after the main Maven execution. * * @since 1.433 */ public DescribableList<Builder, Descriptor<Builder>> getPostbuilders() { return postbuilders; } /** * {@link #postbuilders} are run if the result is better or equal to this threshold. * * @return * never null * @since 1.433 */ public Result getRunPostStepsIfResult() { return Functions.defaulted(runPostStepsIfResult, Result.FAILURE); } public void setRunPostStepsIfResult(Result v) { this.runPostStepsIfResult = Functions.defaulted(v, Result.FAILURE); } public String getUrlChildPrefix() { // seemingly redundant "./" is used to make sure that ':' is not interpreted as the scheme identifier return "."; } public Collection<MavenModule> getItems() { return modules.values(); } @Exported public Collection<MavenModule> getModules() { return getItems(); } public MavenModule getItem(String name) { return modules.get(ModuleName.fromString(name)); } public MavenModule getModule(String name) { return getItem(name); } @Override // to make this accessible from MavenModuleSetBuild protected void updateTransientActions() { super.updateTransientActions(); } protected List<Action> createTransientActions() { List<Action> r = super.createTransientActions(); // 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) r.addAll(step.getProjectActions(this)); if (buildWrappers != null) for (BuildWrapper step : buildWrappers) r.addAll(step.getProjectActions(this)); return r; } protected void addTransientActionsFromBuild(MavenModuleSetBuild build, List<Action> collection, Set<Class> added) { if (build == null) return; for (Action a : build.getActions()) if (a instanceof MavenAggregatedReport) if (added.add(a.getClass())) collection.add(((MavenAggregatedReport) a).getProjectAction(this)); List<MavenReporter> 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) collection.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; } /** * This function recomputes dependency level of each module */ public List<MavenModule> getDisabledModules(boolean disabled) { if (!disabled && sortedActiveModules != null) { // Sort hierarchically Collections.sort(sortedActiveModules, new Comparator<MavenModule>() { public int compare(MavenModule o1, MavenModule o2) { if (o1.depLevel > o2.depLevel) { return 1; } else if (o1.depLevel < o2.depLevel) { return -1; } return 0; } }); return sortedActiveModules; } List<MavenModule> r = new ArrayList<MavenModule>(); for (MavenModule m : modules.values()) { if (m.isDisabled() == disabled) r.add(m); } return r; } public Indenter<MavenModule> createIndenter() { return new Indenter<MavenModule>() { protected int getNestLevel(MavenModule job) { return job.depLevel; } }; } public boolean isIncrementalBuild() { return incrementalBuild; } public boolean isAggregatorStyleBuild() { return aggregatorStyleBuild; } /** * @deprecated as of 1.448 * Use {@link #getLocalRepository()} */ public boolean usesPrivateRepository() { return !(getLocalRepository() instanceof DefaultLocalRepositoryLocator); } public boolean isPerModuleEmail() { return perModuleEmail; } public boolean ignoreUpstremChanges() { return ignoreUpstremChanges; } public boolean runHeadless() { return runHeadless; } public boolean isArchivingDisabled() { return archivingDisabled; } public void setIncrementalBuild(boolean incrementalBuild) { this.incrementalBuild = incrementalBuild; } public void setAggregatorStyleBuild(boolean aggregatorStyleBuild) { this.aggregatorStyleBuild = aggregatorStyleBuild; } /** * @deprecated as of 1.448. * Use {@link #setLocalRepository(LocalRepositoryLocator)} instead */ public void setUsePrivateRepository(boolean usePrivateRepository) { setLocalRepository( usePrivateRepository ? new PerJobLocalRepositoryLocator() : new DefaultLocalRepositoryLocator()); } /** * @return * never null */ public LocalRepositoryLocator getLocalRepository() { return localRepository != null ? localRepository : getDescriptor().getLocalRepository(); } /** * Undefaulted locally configured value with taking inheritance from the global configuration into account. */ public LocalRepositoryLocator getExplicitLocalRepository() { return localRepository; } public void setLocalRepository(LocalRepositoryLocator localRepository) { this.localRepository = localRepository; } public void setIgnoreUpstremChanges(boolean ignoreUpstremChanges) { //this.ignoreUpstremChanges = ignoreUpstremChanges; this.ignoreUpstremChanges = false; } public void setRunHeadless(boolean runHeadless) { this.runHeadless = runHeadless; } public void setIsArchivingDisabled(boolean archivingDisabled) { this.archivingDisabled = archivingDisabled; } public boolean isResolveDependencies() { return resolveDependencies; } public void setResolveDependencies(boolean resolveDependencies) { this.resolveDependencies = resolveDependencies; } public boolean isProcessPlugins() { return processPlugins; } public void setProcessPlugins(boolean processPlugins) { this.processPlugins = processPlugins; } public int getMavenValidationLevel() { return mavenValidationLevel; } /** * @since 1.426 * @return */ public String getSettingConfigId() { return settingConfigId; } /** * @since 1.426 * @param settingConfigId */ public void setSettingConfigId(String settingConfigId) { this.settingConfigId = settingConfigId; } /** * @since 1.426 * @return */ public String getGlobalSettingConfigId() { return globalSettingConfigId; } /** * @since 1.426 * @param globalSettingConfigId */ public void setGlobalSettingConfigId(String globalSettingConfigId) { this.globalSettingConfigId = globalSettingConfigId; } /** * List of active {@link MavenReporter}s that should be applied to all module builds. */ public DescribableList<MavenReporter, Descriptor<MavenReporter>> getReporters() { return reporters; } /** * List of active {@link Publisher}s. Can be empty but never null. */ public DescribableList<Publisher, Descriptor<Publisher>> getPublishers() { return publishers; } @Override public DescribableList<Publisher, Descriptor<Publisher>> getPublishersList() { return publishers; } public DescribableList<BuildWrapper, Descriptor<BuildWrapper>> getBuildWrappersList() { return buildWrappers; } /** * List of active {@link BuildWrapper}s. Can be empty but never null. * * @deprecated as of 1.335 * Use {@link #getBuildWrappersList()} to be consistent with other subtypes of {@link AbstractProject}. */ public DescribableList<BuildWrapper, Descriptor<BuildWrapper>> 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 void onRenamed(MavenModule item, String oldName, String newName) throws IOException { throw new UnsupportedOperationException(); } public void onDeleted(MavenModule item) throws IOException { // noop } public Collection<Job> getAllJobs() { Set<Job> jobs = new HashSet<Job>(getItems()); jobs.add(this); return jobs; } @Override protected Class<MavenModuleSetBuild> getBuildClass() { return MavenModuleSetBuild.class; } @Override protected SearchIndexBuilder makeSearchIndex() { return super.makeSearchIndex().add(new CollectionSearchIndex<MavenModule>() {// for computers protected MavenModule get(String key) { for (MavenModule m : modules.values()) { if (m.getDisplayName().equals(key)) return m; } return null; } protected Collection<MavenModule> all() { return modules.values(); } protected String getName(MavenModule o) { return o.getName(); } }); } @Override public boolean isFingerprintConfigured() { return true; } public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOException { modules = Collections.emptyMap(); // needed during load super.onLoad(parent, name); modules = loadChildren(this, getModulesDir(), new Function1<ModuleName, MavenModule>() { public ModuleName call(MavenModule module) { return module.getModuleName(); } }); // update the transient nest level field. MavenModule root = getRootModule(); if (root != null && root.getChildren() != null) { List<MavenModule> sortedList = new ArrayList<MavenModule>(); Stack<MavenModule> q = new Stack<MavenModule>(); root.nestLevel = 0; q.push(root); while (!q.isEmpty()) { MavenModule p = q.pop(); sortedList.add(p); List<MavenModule> 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<MavenReporter, Descriptor<MavenReporter>>(this); } reporters.setOwner(this); if (publishers == null) { publishers = new DescribableList<Publisher, Descriptor<Publisher>>(this); } publishers.setOwner(this); if (buildWrappers == null) { buildWrappers = new DescribableList<BuildWrapper, Descriptor<BuildWrapper>>(this); } buildWrappers.setOwner(this); if (prebuilders == null) { prebuilders = new DescribableList<Builder, Descriptor<Builder>>(this); } prebuilders.setOwner(this); if (postbuilders == null) { postbuilders = new DescribableList<Builder, Descriptor<Builder>>(this); } postbuilders.setOwner(this); if (perModuleEmail == null) { perModuleEmail = Boolean.TRUE; } if (Boolean.TRUE.equals(usePrivateRepository)) { this.localRepository = new PerJobLocalRepositoryLocator(); usePrivateRepository = null; } 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. * * <p> * 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, InterruptedException { 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) { // the modules are already rebuild by DependencyGraph#init ! // Collection<MavenModule> modules = getModules(); // for (MavenModule m : modules) { // m.buildDependencyGraph(graph); // } publishers.buildDependencyGraph(this, graph); buildWrappers.buildDependencyGraph(this, graph); prebuilders.buildDependencyGraph(this, graph); postbuilders.buildDependencyGraph(this, graph); } public MavenModule getRootModule() { if (rootModule == null) return null; return modules.get(rootModule); } public MavenInstallation inferMavenInstallation() { return getMaven(); } @Override protected Set<ResourceActivity> getResourceActivities() { final Set<ResourceActivity> activities = new HashSet<ResourceActivity>(); activities.addAll(super.getResourceActivities()); activities.addAll(Util.filter(publishers, ResourceActivity.class)); activities.addAll(Util.filter(buildWrappers, ResourceActivity.class)); activities.addAll(Util.filter(prebuilders, ResourceActivity.class)); activities.addAll(Util.filter(postbuilders, ResourceActivity.class)); return activities; } /** * * @deprecated for backward comp only * @return */ public String getRootPOM() { return getRootPOM(null); } /** * Gets the location of top-level <tt>pom.xml</tt> relative to the workspace root. * @since 1.466 */ public String getRootPOM(EnvVars env) { if (rootPOM == null) return "pom.xml"; // JENKINS-13822 if (env == null) return rootPOM; return env.expand(rootPOM); } public void setRootPOM(String rootPOM) { this.rootPOM = 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; } public void setGoals(String goals) { this.goals = goals; } private boolean checkMavenOption(String shortForm, String longForm) { for (String t : Util.tokenize(getGoals())) { if (t.equals(shortForm) || t.equals(longForm)) return true; } return false; } private List<String> getMavenArgument(String shortForm, String longForm) { List<String> args = new ArrayList<String>(); boolean switchFound = false; for (String t : Util.tokenize(getGoals())) { if (switchFound) { args.add(t); switchFound = false; } else if (t.equals(shortForm) || t.equals(longForm)) switchFound = true; else if (t.startsWith(shortForm)) { args.add(t.substring(shortForm.length())); } else if (t.startsWith(longForm)) { args.add(t.substring(longForm.length())); } } return args; } /** * Gets the workspace-relative path to an alternative Maven settings.xml file. */ public String getAlternateSettings() { return alternateSettings; } /** * Sets the workspace-relative path to an alternative Maven settings.xml file. */ public void setAlternateSettings(String alternateSettings) throws IOException { this.alternateSettings = alternateSettings; save(); } /** * If the list of configured goals contain the "-P" option, * return the configured profiles. Otherwise null. */ public String getProfiles() { return Util.join(getMavenArgument("-P", "--activate-profiles"), ","); } /** * Gets the system properties explicitly set in the Maven command line (the "-D" option.) */ public Properties getMavenProperties() { Properties props = new Properties(); for (String arg : getMavenArgument("-D", "--define")) { int idx = arg.indexOf('='); if (idx < 0) props.put(arg, "true"); else props.put(arg.substring(0, idx), arg.substring(idx + 1)); } return props; } /** * Check for "-N" or "--non-recursive" in the Maven goals/options. */ public boolean isNonRecursive() { return checkMavenOption("-N", "--non-recursive"); } /** * Possibly null, whitespace-separated (including TAB, NL, etc) VM options * to be used to launch Maven process. * * If mavenOpts is null or empty, we'll return the globally-defined MAVEN_OPTS. * * <p> * This method returns a configured value as-is, which can include variabl references. * At runtime, use {@link AbstractMavenBuild#getMavenOpts(TaskListener, EnvVars)} to obtain * a fully resolved value. */ public String getMavenOpts() { if ((mavenOpts != null) && (mavenOpts.trim().length() > 0)) { return mavenOpts.replaceAll("[\t\r\n]+", " "); } else { String globalOpts = DESCRIPTOR.getGlobalMavenOpts(); if (globalOpts != null) { return globalOpts.replaceAll("[\t\r\n]+", " "); } else { return globalOpts; } } } // TODO public String getGridLabel() { String gridLabel = DESCRIPTOR.getGridJobsLabel(); if (gridLabel != null) { return gridLabel.replaceAll("[\t\r\n]+", " "); } else { return gridLabel; } } /** * @since 1.426 * @return */ public List<SettingConfig> getAllMavenSettingsConfigs() { return SettingsProviderUtils.getAllMavenSettingsConfigs(); } /** * @since 1.426 * @return */ public List<SettingConfig> getAllGlobalMavenSettingsConfigs() { return SettingsProviderUtils.getAllGlobalMavenSettingsConfigs(); } /** * Set mavenOpts. */ public void setMavenOpts(String mavenOpts) { this.mavenOpts = 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; } public void setMaven(String mavenName) { this.mavenName = mavenName; } /** * Returns the {@link MavenModule}s that are in the queue. */ public List<Queue.Item> getQueueItems() { return filter(Arrays.asList(Jenkins.getInstance().getQueue().getItems())); } /** * Returns the {@link MavenModule}s that are in the queue. */ public List<Queue.Item> getApproximateQueueItemsQuickly() { return filter(Jenkins.getInstance().getQueue().getApproximateItemsQuickly()); } private List<Queue.Item> filter(Collection<Queue.Item> base) { List<Queue.Item> r = new ArrayList<Queue.Item>(); for (Queue.Item item : base) { 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. * * <p> * 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); JSONObject json = req.getSubmittedForm(); rootPOM = Util.fixEmpty(req.getParameter("rootPOM").trim()); if (rootPOM != null && rootPOM.equals("pom.xml")) rootPOM = null; // normalization goals = Util.fixEmpty(req.getParameter("goals").trim()); alternateSettings = Util.fixEmpty(req.getParameter("alternateSettings").trim()); mavenOpts = Util.fixEmpty(req.getParameter("mavenOpts").trim()); mavenName = req.getParameter("maven_version"); aggregatorStyleBuild = !req.hasParameter("maven.perModuleBuild"); if (json.optBoolean("usePrivateRepository")) localRepository = req.bindJSON(LocalRepositoryLocator.class, json.getJSONObject("explicitLocalRepository")); else localRepository = null; perModuleEmail = req.hasParameter("maven.perModuleEmail"); //ignoreUpstremChanges = !json.has("triggerByDependency"); runHeadless = req.hasParameter("maven.runHeadless"); incrementalBuild = req.hasParameter("maven.incrementalBuild"); archivingDisabled = req.hasParameter("maven.archivingDisabled"); resolveDependencies = req.hasParameter("maven.resolveDependencies"); processPlugins = req.hasParameter("maven.processPlugins"); mavenValidationLevel = NumberUtils.toInt(req.getParameter("maven.validationLevel"), -1); reporters.rebuild(req, json, MavenReporters.getConfigurableList()); publishers.rebuildHetero(req, json, Publisher.all(), "publisher"); buildWrappers.rebuild(req, json, BuildWrappers.getFor(this)); settingConfigId = req.getParameter("maven.mavenSettingsConfigId"); globalSettingConfigId = req.getParameter("maven.mavenGlobalSettingConfigId"); runPostStepsIfResult = Result.fromString(req.getParameter("post-steps.runIfResult")); prebuilders.rebuildHetero(req, json, Builder.all(), "prebuilder"); postbuilders.rebuildHetero(req, json, Builder.all(), "postbuilder"); } /** * Delete all disabled modules. */ public HttpResponse doDoDeleteAllDisabledModules() throws IOException, InterruptedException { checkPermission(DELETE); for (MavenModule m : getDisabledModules(true)) m.delete(); return HttpResponses.redirectToDot(); } /** * Check the location of the POM, alternate settings file, etc - any file. */ public FormValidation doCheckFileInWorkspace(@QueryParameter String value) throws IOException, ServletException { MavenModuleSetBuild lb = getLastBuild(); if (lb != null) { FilePath ws = lb.getModuleRoot(); if (ws != null) return ws.validateRelativePath(value, true, true); } return FormValidation.ok(); } /** * Check that the provided file is a relative path. And check that it exists, just in case. */ public FormValidation doCheckFileRelative(@QueryParameter String value) throws IOException, ServletException { String v = fixEmpty(value); if ((v == null) || (v.length() == 0)) { // Null values are allowed. return FormValidation.ok(); } if ((v.startsWith("/")) || (v.startsWith("\\")) || (v.matches("^\\w\\:\\\\.*"))) { return FormValidation.error(Messages.MavenModuleSet_AlternateSettingsRelativePath()); } MavenModuleSetBuild lb = getLastBuild(); if (lb != null) { FilePath ws = lb.getWorkspace(); if (ws != null) return ws.validateRelativePath(value, true, true); } return FormValidation.ok(); } public DescriptorImpl getDescriptor() { return DESCRIPTOR; } @Extension(ordinal = 900) public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); public static final class DescriptorImpl extends AbstractProjectDescriptor { /** * Globally-defined MAVEN_OPTS. */ private String globalMavenOpts; private String gridJobsLabel; /** * @since 1.394 */ private Map<String, Integer> mavenValidationLevels = new LinkedHashMap<String, Integer>(); /** * @since 1.448 */ private LocalRepositoryLocator localRepository = new DefaultLocalRepositoryLocator(); public DescriptorImpl() { super(); load(); mavenValidationLevels.put("DEFAULT", -1); mavenValidationLevels.put("LEVEL_MINIMAL", ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL); mavenValidationLevels.put("LEVEL_MAVEN_2_0", ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0); mavenValidationLevels.put("LEVEL_MAVEN_3_0", ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0); mavenValidationLevels.put("LEVEL_MAVEN_3_1", ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_1); mavenValidationLevels.put("LEVEL_STRICT", ModelBuildingRequest.VALIDATION_LEVEL_STRICT); } public String getGlobalMavenOpts() { return globalMavenOpts; } public String getGridJobsLabel() { return gridJobsLabel; } public void setGlobalMavenOpts(String globalMavenOpts) { this.globalMavenOpts = globalMavenOpts; save(); } /** * @return never null. */ public LocalRepositoryLocator getLocalRepository() { return localRepository != null ? localRepository : new DefaultLocalRepositoryLocator(); } public void setLocalRepository(LocalRepositoryLocator localRepository) { this.localRepository = localRepository; save(); } public String getDisplayName() { return Messages.MavenModuleSet_DiplayName(); } public MavenModuleSet newInstance(ItemGroup parent, String name) { return new MavenModuleSet(parent, name); } public Maven.DescriptorImpl getMavenDescriptor() { return Jenkins.getInstance().getDescriptorByType(Maven.DescriptorImpl.class); } /** * @since 1.394 * @return */ public Map<String, Integer> getMavenValidationLevels() { return mavenValidationLevels; } @Override public boolean configure(StaplerRequest req, JSONObject o) { globalMavenOpts = Util.fixEmptyAndTrim(o.getString("globalMavenOpts")); gridJobsLabel = Util.fixEmptyAndTrim(o.getString("gridJobsLabel")); localRepository = req.bindJSON(LocalRepositoryLocator.class, o.getJSONObject("localRepository")); save(); return true; } @Override public boolean isApplicable(Descriptor descriptor) { return !NOT_APPLICABLE_TYPES.contains(descriptor.clazz); } private static final Set<Class> NOT_APPLICABLE_TYPES = new HashSet<Class>(Arrays.asList(Fingerprinter.class, // this kicks in automatically JavadocArchiver.class, // this kicks in automatically Mailer.class, // for historical reasons, Maven uses MavenMailer JUnitResultArchiver.class // done by SurefireArchiver )); } }