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.Component;
32  import org.apache.maven.plugins.annotations.Parameter;
33  import org.apache.maven.project.MavenProject;
34  import org.apache.maven.settings.Settings;
35  import org.apache.maven.shared.release.ReleaseManager;
36  import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder;
37  import org.apache.maven.shared.release.env.DefaultReleaseEnvironment;
38  import org.apache.maven.shared.release.env.ReleaseEnvironment;
39  import org.codehaus.plexus.util.StringUtils;
40  
41  /**
42   * Base class with shared configuration.
43   *
44   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
45   */
46  public abstract class AbstractReleaseMojo extends AbstractMojo {
47      /**
48       */
49      @Parameter(defaultValue = "${basedir}", readonly = true, required = true)
50      private File basedir;
51  
52      /**
53       */
54      @Parameter(defaultValue = "${settings}", readonly = true, required = true)
55      private Settings settings;
56  
57      /**
58       */
59      @Parameter(defaultValue = "${project}", readonly = true, required = true)
60      protected MavenProject project;
61  
62      /**
63       */
64      @Component
65      protected ReleaseManager releaseManager;
66  
67      /**
68       * Additional arguments to pass to the Maven executions, separated by spaces.
69       */
70      @Parameter(alias = "prepareVerifyArgs", property = "arguments")
71      private String arguments;
72  
73      /**
74       * The file name of the POM to execute any goals against. As of version 3.0.0, this defaults to the name of
75       * POM file of the project being built.
76       */
77      @Parameter(property = "pomFileName", defaultValue = "${project.file.name}")
78      private String pomFileName;
79  
80      /**
81       */
82      @Parameter(defaultValue = "${reactorProjects}", readonly = true, required = true)
83      private List<MavenProject> reactorProjects;
84  
85      /**
86       * The Maven home parameter to use for forked Maven invocations.
87       *
88       * @since 2.0-beta-8
89       */
90      @Parameter(defaultValue = "${maven.home}")
91      private File mavenHome;
92  
93      /**
94       * The Java home parameter to use for forked Maven invocations.
95       *
96       * @since 2.0-beta-8
97       */
98      @Parameter(defaultValue = "${java.home}")
99      private File javaHome;
100 
101     /**
102      * The command-line local repository directory in use for this build (if specified).
103      *
104      * @since 2.0-beta-8
105      */
106     @Parameter(defaultValue = "${maven.repo.local}")
107     private File localRepoDirectory;
108 
109     /**
110      * Role hint of the {@link org.apache.maven.shared.release.exec.MavenExecutor} implementation to use.
111      *
112      * @since 2.0-beta-8
113      */
114     @Parameter(defaultValue = "invoker", property = "mavenExecutorId")
115     private String mavenExecutorId;
116 
117     /**
118      * @since 2.0
119      */
120     @Parameter(defaultValue = "${session}", readonly = true, required = true)
121     protected MavenSession session;
122 
123     /**
124      * The role-hint for the {@link org.apache.maven.shared.release.strategy.Strategy}
125      * implementation used to specify the phases per goal.
126      *
127      * @since 3.0.0-M5
128      * @see org.apache.maven.shared.release.strategies.DefaultStrategy
129      */
130     @Parameter(defaultValue = "default", property = "releaseStrategyId")
131     private String releaseStrategyId;
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 }