1 package org.apache.maven.plugins.release;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.io.File;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.apache.maven.execution.MavenSession;
28 import org.apache.maven.model.Profile;
29 import org.apache.maven.plugin.AbstractMojo;
30 import org.apache.maven.plugin.MojoExecutionException;
31 import org.apache.maven.plugin.MojoFailureException;
32 import org.apache.maven.project.MavenProject;
33 import org.apache.maven.scm.manager.ScmManager;
34 import org.apache.maven.settings.Settings;
35 import org.apache.maven.shared.release.ReleaseManager;
36 import org.apache.maven.shared.release.config.ReleaseDescriptor;
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 * @version $Id: AbstractReleaseMojo.html 816531 2012-05-08 11:38:11Z hboutemy $
46 */
47 public abstract class AbstractReleaseMojo
48 extends AbstractMojo
49 {
50 /**
51 * The SCM username to use.
52 *
53 * @parameter expression="${username}"
54 */
55 private String username;
56
57 /**
58 * The SCM password to use.
59 *
60 * @parameter expression="${password}"
61 */
62 private String password;
63
64 /**
65 * The SCM tag to use.
66 *
67 * @parameter expression="${tag}" alias="releaseLabel"
68 */
69 private String tag;
70
71 /**
72 * Format to use when generating the tag name if none is specified. Property interpolation is performed on the
73 * tag, but in order to ensure that the interpolation occurs during release, you must use <code>@{...}</code>
74 * to reference the properties rather than <code>${...}</code>. The following properties are available:
75 * <ul>
76 * <li><code>groupId</code> or <code>project.groupId</code> - The groupId of the root project.
77 * <li><code>artifactId</code> or <code>project.artifactId</code> - The artifactId of the root project.
78 * <li><code>version</code> or <code>project.version</code> - The release version of the root project.
79 * </ul>
80 *
81 * @parameter expression="${tagNameFormat}" default-value="@{project.artifactId}-@{project.version}"
82 * @since 2.2.0
83 */
84 private String tagNameFormat;
85
86 /**
87 * The tag base directory in SVN, you must define it if you don't use the standard svn layout (trunk/tags/branches).
88 * For example, <code>http://svn.apache.org/repos/asf/maven/plugins/tags</code>. The URL is an SVN URL and does not
89 * include the SCM provider and protocol.
90 *
91 * @parameter expression="${tagBase}"
92 */
93 private String tagBase;
94
95 /**
96 * @parameter expression="${basedir}"
97 * @required
98 * @readonly
99 */
100 protected File basedir;
101
102 /**
103 * @parameter expression="${settings}"
104 * @required
105 * @readonly
106 */
107 protected Settings settings;
108
109 /**
110 * @parameter expression="${project}"
111 * @required
112 * @readonly
113 */
114 protected MavenProject project;
115
116 /**
117 * @component
118 */
119 protected ReleaseManager releaseManager;
120
121 /**
122 * Additional arguments to pass to the Maven executions, separated by spaces.
123 *
124 * @parameter expression="${arguments}" alias="prepareVerifyArgs"
125 */
126 private String arguments;
127
128 /**
129 * The file name of the POM to execute any goals against.
130 *
131 * @parameter expression="${pomFileName}"
132 */
133 private String pomFileName;
134
135 /**
136 * The message prefix to use for all SCM changes.
137 *
138 * @parameter expression="${scmCommentPrefix}" default-value="[maven-release-plugin] "
139 * @since 2.0-beta-5
140 */
141 private String scmCommentPrefix;
142
143 /**
144 * @parameter expression="${reactorProjects}"
145 * @required
146 * @readonly
147 */
148 protected List reactorProjects;
149
150 /**
151 * List of provider implementations.
152 *
153 * @parameter
154 * @since 2.0-beta-6
155 */
156 private Map providerImplementations;
157
158 /**
159 * The M2_HOME parameter to use for forked Maven invocations.
160 *
161 * @parameter default-value="${maven.home}"
162 * @since 2.0-beta-8
163 */
164 protected File mavenHome;
165
166 /**
167 * The JAVA_HOME parameter to use for forked Maven invocations.
168 *
169 * @parameter default-value="${java.home}"
170 * @since 2.0-beta-8
171 */
172 protected File javaHome;
173
174 /**
175 * The command-line local repository directory in use for this build (if specified).
176 *
177 * @parameter default-value="${maven.repo.local}"
178 * @since 2.0-beta-8
179 */
180 protected File localRepoDirectory;
181
182 /**
183 * Role hint of the {@link org.apache.maven.shared.release.exec.MavenExecutor} implementation to use.
184 *
185 * @parameter expression="${mavenExecutorId}" default-value="invoker"
186 * @since 2.0-beta-8
187 */
188 protected String mavenExecutorId;
189
190 /**
191 * Use a local checkout instead of doing a checkout from the upstream repository.
192 * ATTENTION: This will only work with distributed SCMs which support the file:// protocol
193 * like e.g. git, jgit or hg!
194 *
195 * TODO: we should think about having the defaults for the various SCM providers provided via modello!
196 *
197 * @parameter expression="${localCheckout}" default-value="false"
198 * @since 2.0
199 */
200 private boolean localCheckout;
201
202 /**
203 * Implemented with git will or not push changes to the upstream repository.
204 * <code>true</code> by default to preserve backward compatibility.
205 * @parameter expression="${pushChanges}" default-value="true"
206 * @since 2.1
207 */
208 private boolean pushChanges = true;
209
210 /**
211 * The SCM manager.
212 *
213 * @component
214 */
215 private ScmManager scmManager;
216
217 /**
218 * @parameter expression="${session}"
219 * @readonly
220 * @required
221 * @since 2.0
222 */
223 protected MavenSession session;
224
225
226 /**
227 * Gets the enviroment settings configured for this release.
228 *
229 * @return The release environment, never <code>null</code>.
230 */
231 protected ReleaseEnvironment getReleaseEnvironment()
232 {
233 return new DefaultReleaseEnvironment().setSettings( settings )
234 .setJavaHome( javaHome )
235 .setMavenHome( mavenHome )
236 .setLocalRepositoryDirectory( localRepoDirectory )
237 .setMavenExecutorId( mavenExecutorId );
238 }
239
240 /**
241 * {@inheritDoc}
242 */
243 public void execute()
244 throws MojoExecutionException, MojoFailureException
245 {
246 if ( providerImplementations != null )
247 {
248 for ( Iterator i = providerImplementations.keySet().iterator(); i.hasNext(); )
249 {
250 String providerType = (String) i.next();
251 String providerImplementation = (String) providerImplementations.get( providerType );
252 getLog().info( "Change the default '" + providerType + "' provider implementation to '"
253 + providerImplementation + "'." );
254 scmManager.setScmProviderImplementation( providerType, providerImplementation );
255 }
256 }
257 }
258
259 /**
260 * Creates the release descriptor from the various goal parameters.
261 *
262 * @return The release descriptor, never <code>null</code>.
263 */
264 protected ReleaseDescriptor createReleaseDescriptor()
265 {
266 ReleaseDescriptor descriptor = new ReleaseDescriptor();
267
268 descriptor.setInteractive( settings.isInteractiveMode() );
269
270 descriptor.setScmPassword( password );
271 descriptor.setScmReleaseLabel( tag );
272 descriptor.setScmTagNameFormat( tagNameFormat );
273 descriptor.setScmTagBase( tagBase );
274 descriptor.setScmUsername( username );
275 descriptor.setScmCommentPrefix( scmCommentPrefix );
276
277 descriptor.setWorkingDirectory( basedir.getAbsolutePath() );
278
279 descriptor.setPomFileName( pomFileName );
280
281 descriptor.setLocalCheckout( localCheckout );
282
283 descriptor.setPushChanges( pushChanges );
284
285 List profiles = project.getActiveProfiles();
286
287 String arguments = this.arguments;
288 if ( profiles != null && !profiles.isEmpty() )
289 {
290 if ( !StringUtils.isEmpty( arguments ) )
291 {
292 arguments += " -P ";
293 }
294 else
295 {
296 arguments = "-P ";
297 }
298
299 for ( Iterator it = profiles.iterator(); it.hasNext(); )
300 {
301 Profile profile = (Profile) it.next();
302
303 arguments += profile.getId();
304 if ( it.hasNext() )
305 {
306 arguments += ",";
307 }
308 }
309
310 String additionalProfiles = getAdditionalProfiles();
311 if ( additionalProfiles != null )
312 {
313 if ( !profiles.isEmpty() )
314 {
315 arguments += ",";
316 }
317 arguments += additionalProfiles;
318 }
319 }
320 descriptor.setAdditionalArguments( arguments );
321
322 return descriptor;
323 }
324
325 /**
326 * Gets the comma separated list of additional profiles for the release build.
327 *
328 * @return additional profiles to enable during release
329 */
330 protected String getAdditionalProfiles()
331 {
332 return null;
333 }
334
335 /**
336 * Sets the component used to perform release actions.
337 *
338 * @param releaseManager The release manager implementation to use, must not be <code>null</code>.
339 */
340 void setReleaseManager( ReleaseManager releaseManager )
341 {
342 this.releaseManager = releaseManager;
343 }
344
345 /**
346 * Gets the effective settings for this build.
347 *
348 * @return The effective settings for this build, never <code>null</code>.
349 */
350 Settings getSettings()
351 {
352 return settings;
353 }
354
355 /**
356 * Sets the base directory of the build.
357 *
358 * @param basedir The build's base directory, must not be <code>null</code>.
359 */
360 public void setBasedir( File basedir )
361 {
362 this.basedir = basedir;
363 }
364
365 /**
366 * Gets the list of projects in the build reactor.
367 *
368 * @return The list of reactor project, never <code>null</code>.
369 */
370 public List getReactorProjects()
371 {
372 return reactorProjects;
373 }
374
375 /**
376 * Add additional arguments.
377 *
378 * @param argument The argument to add, must not be <code>null</code>.
379 */
380 protected void addArgument( String argument )
381 {
382 if ( arguments != null )
383 {
384 arguments += " " + argument;
385 }
386 else
387 {
388 arguments = argument;
389 }
390 }
391
392 /**
393 * This method takes some of the release configuration picked up from the command line system properties and copies
394 * it into the release config object.
395 *
396 * @param config The release configuration to merge the system properties into, must not be <code>null</code>.
397 * @param sysPropertiesConfig The configuration from the system properties to merge in, must not be
398 * <code>null</code>.
399 */
400 protected void mergeCommandLineConfig( ReleaseDescriptor config, ReleaseDescriptor sysPropertiesConfig )
401 {
402 // If the user specifies versions, these should override the existing versions
403 if ( sysPropertiesConfig.getReleaseVersions() != null )
404 {
405 config.getReleaseVersions().putAll( sysPropertiesConfig.getReleaseVersions() );
406 }
407 if ( sysPropertiesConfig.getDevelopmentVersions() != null )
408 {
409 config.getDevelopmentVersions().putAll( sysPropertiesConfig.getDevelopmentVersions() );
410 }
411 }
412 }