View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.release;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.nio.file.Path;
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.List;
27  
28  import org.apache.maven.artifact.ArtifactUtils;
29  import org.apache.maven.execution.MavenSession;
30  import org.apache.maven.plugin.AbstractMojo;
31  import org.apache.maven.plugins.annotations.Parameter;
32  import org.apache.maven.project.MavenProject;
33  import org.apache.maven.settings.Settings;
34  import org.apache.maven.shared.release.ReleaseManager;
35  import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder;
36  import org.apache.maven.shared.release.env.DefaultReleaseEnvironment;
37  import org.apache.maven.shared.release.env.ReleaseEnvironment;
38  import org.codehaus.plexus.util.StringUtils;
39  
40  /**
41   * Base class with shared configuration.
42   *
43   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
44   */
45  public abstract class AbstractReleaseMojo extends AbstractMojo {
46      /**
47       */
48      @Parameter(defaultValue = "${basedir}", readonly = true, required = true)
49      private File basedir;
50  
51      /**
52       */
53      @Parameter(defaultValue = "${settings}", readonly = true, required = true)
54      private Settings settings;
55  
56      /**
57       */
58      @Parameter(defaultValue = "${project}", readonly = true, required = true)
59      protected MavenProject project;
60  
61      /**
62       * Additional arguments to pass to the Maven executions, separated by spaces.
63       */
64      @Parameter(alias = "prepareVerifyArgs", property = "arguments")
65      private String arguments;
66  
67      /**
68       * The file name of the POM to execute any goals against. As of version 3.0.0, this defaults to the name of
69       * POM file of the project being built.
70       */
71      @Parameter(property = "pomFileName", defaultValue = "${project.file.name}")
72      private String pomFileName;
73  
74      /**
75       */
76      @Parameter(defaultValue = "${reactorProjects}", readonly = true, required = true)
77      private List<MavenProject> reactorProjects;
78  
79      /**
80       * The Maven home parameter to use for forked Maven invocations.
81       *
82       * @since 2.0-beta-8
83       */
84      @Parameter(defaultValue = "${maven.home}")
85      private File mavenHome;
86  
87      /**
88       * The Java home parameter to use for forked Maven invocations.
89       *
90       * @since 2.0-beta-8
91       */
92      @Parameter(defaultValue = "${java.home}")
93      private File javaHome;
94  
95      /**
96       * The command-line local repository directory in use for this build (if specified).
97       *
98       * @since 2.0-beta-8
99       */
100     @Parameter(defaultValue = "${maven.repo.local}")
101     private File localRepoDirectory;
102 
103     /**
104      * Role hint of the {@link org.apache.maven.shared.release.exec.MavenExecutor} implementation to use.
105      *
106      * @since 2.0-beta-8
107      */
108     @Parameter(defaultValue = "invoker", property = "mavenExecutorId")
109     private String mavenExecutorId;
110 
111     /**
112      * @since 2.0
113      */
114     @Parameter(defaultValue = "${session}", readonly = true, required = true)
115     protected MavenSession session;
116 
117     /**
118      * The role-hint for the {@link org.apache.maven.shared.release.strategy.Strategy}
119      * implementation used to specify the phases per goal.
120      *
121      * @since 3.0.0-M5
122      * @see org.apache.maven.shared.release.strategies.DefaultStrategy
123      */
124     @Parameter(defaultValue = "default", property = "releaseStrategyId")
125     private String releaseStrategyId;
126 
127     protected ReleaseManager releaseManager;
128 
129     protected AbstractReleaseMojo(ReleaseManager releaseManager) {
130         this.releaseManager = releaseManager;
131     }
132 
133     /**
134      * Gets the environment settings configured for this release.
135      *
136      * @return The release environment, never <code>null</code>.
137      */
138     protected ReleaseEnvironment getReleaseEnvironment() {
139         return new DefaultReleaseEnvironment()
140                 .setSettings(settings)
141                 .setJavaHome(javaHome)
142                 .setMavenHome(mavenHome)
143                 .setLocalRepositoryDirectory(localRepoDirectory)
144                 .setMavenExecutorId(mavenExecutorId);
145     }
146 
147     /**
148      * Creates the release descriptor from the various goal parameters.
149      *
150      * @return The release descriptor, never <code>null</code>.
151      */
152     protected ReleaseDescriptorBuilder createReleaseDescriptor() {
153         ReleaseDescriptorBuilder descriptor = new ReleaseDescriptorBuilder();
154 
155         descriptor.setInteractive(settings.isInteractiveMode());
156 
157         Path workingDirectory;
158         try {
159             workingDirectory = getCommonBasedir(reactorProjects);
160         } catch (IOException e) {
161             throw new RuntimeException(e.getMessage());
162         }
163         descriptor.setWorkingDirectory(workingDirectory.toFile().getAbsolutePath());
164 
165         Path rootBasedir = basedir.toPath();
166         if (rootBasedir.equals(workingDirectory)) {
167             descriptor.setPomFileName(pomFileName);
168         } else {
169             descriptor.setPomFileName(workingDirectory
170                     .relativize(rootBasedir)
171                     .resolve(pomFileName)
172                     .toString());
173         }
174 
175         for (MavenProject project : reactorProjects) {
176             String versionlessKey = ArtifactUtils.versionlessKey(project.getGroupId(), project.getArtifactId());
177             descriptor.putOriginalVersion(versionlessKey, project.getVersion());
178         }
179 
180         descriptor.setAdditionalArguments(this.arguments);
181 
182         List<String> profileIds = session.getRequest().getActiveProfiles();
183         String additionalProfiles = getAdditionalProfiles();
184 
185         if (!profileIds.isEmpty() || StringUtils.isNotBlank(additionalProfiles)) {
186             List<String> profiles = new ArrayList<>(profileIds);
187 
188             if (additionalProfiles != null) {
189                 profiles.addAll(Arrays.asList(additionalProfiles.split(",")));
190             }
191 
192             descriptor.setActivateProfiles(profiles);
193         }
194 
195         descriptor.setReleaseStrategyId(releaseStrategyId);
196 
197         return descriptor;
198     }
199 
200     /**
201      * Gets the comma separated list of additional profiles for the release build.
202      *
203      * @return additional profiles to enable during release
204      */
205     protected String getAdditionalProfiles() {
206         return null;
207     }
208 
209     /**
210      * Sets the component used to perform release actions.
211      *
212      * @param releaseManager The release manager implementation to use, must not be <code>null</code>.
213      */
214     void setReleaseManager(ReleaseManager releaseManager) {
215         this.releaseManager = releaseManager;
216     }
217 
218     /**
219      * Gets the effective settings for this build.
220      *
221      * @return The effective settings for this build, never <code>null</code>.
222      */
223     Settings getSettings() {
224         return settings;
225     }
226 
227     protected final File getBasedir() {
228         return basedir;
229     }
230 
231     /**
232      * Sets the base directory of the build.
233      *
234      * @param basedir The build's base directory, must not be <code>null</code>.
235      */
236     public void setBasedir(File basedir) {
237         this.basedir = basedir;
238     }
239 
240     public void setPomFileName(String pomFileName) {
241         this.pomFileName = pomFileName;
242     }
243 
244     /**
245      * only used for unit tests in which some required values of the project would be null
246      */
247     protected MavenProject getProject() {
248         return this.project;
249     }
250 
251     /**
252      * Gets the list of projects in the build reactor.
253      *
254      * @return The list of reactor project, never <code>null</code>.
255      */
256     public List<MavenProject> getReactorProjects() {
257         return reactorProjects;
258     }
259 
260     /**
261      * Add additional arguments.
262      *
263      * @param argument The argument to add, must not be <code>null</code>.
264      */
265     protected void addArgument(String argument) {
266         if (arguments != null) {
267             arguments += " " + argument;
268         } else {
269             arguments = argument;
270         }
271     }
272 
273     static Path getCommonBasedir(List<MavenProject> reactorProjects) throws IOException {
274         Path basePath = reactorProjects.get(0).getBasedir().toPath();
275 
276         for (MavenProject reactorProject : reactorProjects) {
277             Path matchPath = reactorProject.getBasedir().toPath();
278             while (!basePath.startsWith(matchPath)) {
279                 matchPath = matchPath.getParent();
280             }
281             basePath = matchPath;
282         }
283 
284         return basePath;
285     }
286 }