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.java 1333174 2012-05-02 19:52:18Z rfscholte $ 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 default-value="${basedir}" 97 * @required 98 * @readonly 99 */ 100 private File basedir; 101 102 /** 103 * @parameter default-value="${settings}" 104 * @required 105 * @readonly 106 */ 107 private Settings settings; 108 109 /** 110 * @parameter default-value="${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 default-value="${reactorProjects}" 145 * @required 146 * @readonly 147 */ 148 private List<MavenProject> reactorProjects; 149 150 /** 151 * Add a new or overwrite the default implementation per provider. 152 * The key is the scm prefix and the value is the role hint of the {@link org.apache.maven.scm.provider.ScmProvider}. 153 * 154 * @parameter 155 * @since 2.0-beta-6 156 * @see ScmManager#setScmProviderImplementation(String, String) 157 */ 158 private Map<String, String> providerImplementations; 159 160 /** 161 * The {@code M2_HOME} parameter to use for forked Maven invocations. 162 * 163 * @parameter default-value="${maven.home}" 164 * @since 2.0-beta-8 165 */ 166 protected File mavenHome; 167 168 /** 169 * The {@code JAVA_HOME} parameter to use for forked Maven invocations. 170 * 171 * @parameter default-value="${java.home}" 172 * @since 2.0-beta-8 173 */ 174 private File javaHome; 175 176 /** 177 * The command-line local repository directory in use for this build (if specified). 178 * 179 * @parameter default-value="${maven.repo.local}" 180 * @since 2.0-beta-8 181 */ 182 private File localRepoDirectory; 183 184 /** 185 * Role hint of the {@link org.apache.maven.shared.release.exec.MavenExecutor} implementation to use. 186 * 187 * @parameter expression="${mavenExecutorId}" default-value="invoker" 188 * @since 2.0-beta-8 189 */ 190 private String mavenExecutorId; 191 192 /** 193 * Use a local checkout instead of doing a checkout from the upstream repository. 194 * ATTENTION: This will only work with distributed SCMs which support the file:// protocol 195 * like e.g. git, jgit or hg! 196 * 197 * TODO: we should think about having the defaults for the various SCM providers provided via modello! 198 * 199 * @parameter expression="${localCheckout}" default-value="false" 200 * @since 2.0 201 */ 202 private boolean localCheckout; 203 204 /** 205 * Implemented with git will or not push changes to the upstream repository. 206 * <code>true</code> by default to preserve backward compatibility. 207 * @parameter expression="${pushChanges}" default-value="true" 208 * @since 2.1 209 */ 210 private boolean pushChanges = true; 211 212 /** 213 * The SCM manager. 214 * 215 * @component 216 */ 217 private ScmManager scmManager; 218 219 /** 220 * @parameter default-value="${session}" 221 * @readonly 222 * @required 223 * @since 2.0 224 */ 225 protected MavenSession session; 226 227 228 /** 229 * Gets the enviroment settings configured for this release. 230 * 231 * @return The release environment, never <code>null</code>. 232 */ 233 protected ReleaseEnvironment getReleaseEnvironment() 234 { 235 return new DefaultReleaseEnvironment().setSettings( settings ) 236 .setJavaHome( javaHome ) 237 .setMavenHome( mavenHome ) 238 .setLocalRepositoryDirectory( localRepoDirectory ) 239 .setMavenExecutorId( mavenExecutorId ); 240 } 241 242 /** 243 * {@inheritDoc} 244 */ 245 public void execute() 246 throws MojoExecutionException, MojoFailureException 247 { 248 if ( providerImplementations != null ) 249 { 250 for ( Map.Entry<String, String> providerEntry : providerImplementations.entrySet() ) 251 { 252 getLog().info( "Change the default '" + providerEntry.getKey() + "' provider implementation to '" 253 + providerEntry.getValue() + "'." ); 254 scmManager.setScmProviderImplementation( providerEntry.getKey(), providerEntry.getValue() ); 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 @SuppressWarnings("unchecked") 286 List<Profile> profiles = project.getActiveProfiles(); 287 288 String arguments = this.arguments; 289 if ( profiles != null && !profiles.isEmpty() ) 290 { 291 if ( !StringUtils.isEmpty( arguments ) ) 292 { 293 arguments += " -P "; 294 } 295 else 296 { 297 arguments = "-P "; 298 } 299 300 for ( Iterator<Profile> it = profiles.iterator(); it.hasNext(); ) 301 { 302 Profile profile = it.next(); 303 304 arguments += profile.getId(); 305 if ( it.hasNext() ) 306 { 307 arguments += ","; 308 } 309 } 310 311 String additionalProfiles = getAdditionalProfiles(); 312 if ( additionalProfiles != null ) 313 { 314 if ( !profiles.isEmpty() ) 315 { 316 arguments += ","; 317 } 318 arguments += additionalProfiles; 319 } 320 } 321 descriptor.setAdditionalArguments( arguments ); 322 323 return descriptor; 324 } 325 326 /** 327 * Gets the comma separated list of additional profiles for the release build. 328 * 329 * @return additional profiles to enable during release 330 */ 331 protected String getAdditionalProfiles() 332 { 333 return null; 334 } 335 336 /** 337 * Sets the component used to perform release actions. 338 * 339 * @param releaseManager The release manager implementation to use, must not be <code>null</code>. 340 */ 341 void setReleaseManager( ReleaseManager releaseManager ) 342 { 343 this.releaseManager = releaseManager; 344 } 345 346 /** 347 * Gets the effective settings for this build. 348 * 349 * @return The effective settings for this build, never <code>null</code>. 350 */ 351 Settings getSettings() 352 { 353 return settings; 354 } 355 356 protected final File getBasedir() 357 { 358 return basedir; 359 } 360 361 /** 362 * Sets the base directory of the build. 363 * 364 * @param basedir The build's base directory, must not be <code>null</code>. 365 */ 366 public void setBasedir( File basedir ) 367 { 368 this.basedir = basedir; 369 } 370 371 /** 372 * Gets the list of projects in the build reactor. 373 * 374 * @return The list of reactor project, never <code>null</code>. 375 */ 376 public List<MavenProject> getReactorProjects() 377 { 378 return reactorProjects; 379 } 380 381 /** 382 * Add additional arguments. 383 * 384 * @param argument The argument to add, must not be <code>null</code>. 385 */ 386 protected void addArgument( String argument ) 387 { 388 if ( arguments != null ) 389 { 390 arguments += " " + argument; 391 } 392 else 393 { 394 arguments = argument; 395 } 396 } 397 398 /** 399 * This method takes some of the release configuration picked up from the command line system properties and copies 400 * it into the release config object. 401 * 402 * @param config The release configuration to merge the system properties into, must not be <code>null</code>. 403 * @param sysPropertiesConfig The configuration from the system properties to merge in, must not be 404 * <code>null</code>. 405 */ 406 protected void mergeCommandLineConfig( ReleaseDescriptor config, ReleaseDescriptor sysPropertiesConfig ) 407 { 408 // If the user specifies versions, these should override the existing versions 409 if ( sysPropertiesConfig.getReleaseVersions() != null ) 410 { 411 config.getReleaseVersions().putAll( sysPropertiesConfig.getReleaseVersions() ); 412 } 413 if ( sysPropertiesConfig.getDevelopmentVersions() != null ) 414 { 415 config.getDevelopmentVersions().putAll( sysPropertiesConfig.getDevelopmentVersions() ); 416 } 417 } 418 }