| package org.apache.maven.scm.plugin; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Properties; |
| |
| import org.apache.maven.plugin.AbstractMojo; |
| import org.apache.maven.plugin.MojoExecutionException; |
| import org.apache.maven.scm.ScmBranch; |
| import org.apache.maven.scm.ScmException; |
| import org.apache.maven.scm.ScmFileSet; |
| import org.apache.maven.scm.ScmResult; |
| import org.apache.maven.scm.ScmRevision; |
| import org.apache.maven.scm.ScmTag; |
| import org.apache.maven.scm.ScmVersion; |
| import org.apache.maven.scm.manager.ScmManager; |
| import org.apache.maven.scm.provider.ScmProviderRepository; |
| import org.apache.maven.scm.provider.ScmProviderRepositoryWithHost; |
| import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository; |
| import org.apache.maven.scm.repository.ScmRepository; |
| import org.apache.maven.scm.repository.ScmRepositoryException; |
| import org.apache.maven.settings.Server; |
| import org.apache.maven.settings.Settings; |
| import org.apache.maven.shared.model.fileset.FileSet; |
| import org.apache.maven.shared.model.fileset.util.FileSetManager; |
| import org.codehaus.plexus.util.StringUtils; |
| import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; |
| import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException; |
| |
| /** |
| * @author <a href="evenisse@apache.org">Emmanuel Venisse</a> |
| * @author Olivier Lamy |
| * @version $Id$ |
| */ |
| public abstract class AbstractScmMojo |
| extends AbstractMojo |
| { |
| /** |
| * The SCM connection URL. |
| * |
| * @parameter expression="${connectionUrl}" default-value="${project.scm.connection}" |
| */ |
| private String connectionUrl; |
| |
| /** |
| * The SCM connection URL for developers. |
| * |
| * @parameter expression="${connectionUrl}" default-value="${project.scm.developerConnection}" |
| */ |
| private String developerConnectionUrl; |
| |
| /** |
| * The type of connection to use (connection or developerConnection). |
| * |
| * @parameter expression="${connectionType}" default-value="connection" |
| */ |
| private String connectionType; |
| |
| /** |
| * The working directory. |
| * |
| * @parameter expression="${workingDirectory}" |
| */ |
| private File workingDirectory; |
| |
| /** |
| * The user name (used by svn, starteam and perforce protocol). |
| * |
| * @parameter expression="${username}" |
| */ |
| private String username; |
| |
| /** |
| * The user password (used by svn, starteam and perforce protocol). |
| * |
| * @parameter expression="${password}" |
| */ |
| private String password; |
| |
| /** |
| * The private key (used by java svn). |
| * |
| * @parameter expression="${privateKey}" |
| */ |
| private String privateKey; |
| |
| /** |
| * The passphrase (used by java svn). |
| * |
| * @parameter expression="${passphrase}" |
| */ |
| private String passphrase; |
| |
| /** |
| * The url of tags base directory (used by svn protocol). It is not |
| * necessary to set it if you use the standard svn layout |
| * (branches/tags/trunk). |
| * |
| * @parameter expression="${tagBase}" |
| */ |
| private String tagBase; |
| |
| /** |
| * Comma separated list of includes file pattern. |
| * |
| * @parameter expression="${includes}" |
| */ |
| private String includes; |
| |
| /** |
| * Comma separated list of excludes file pattern. |
| * |
| * @parameter expression="${excludes}" |
| */ |
| private String excludes; |
| |
| /** |
| * @component |
| */ |
| private ScmManager manager; |
| |
| /** |
| * When this plugin requires Maven 3.0 as minimum, this component can be removed and o.a.m.s.c.SettingsDecrypter be |
| * used instead. |
| * |
| * @component roleHint="mng-4384" |
| */ |
| private SecDispatcher secDispatcher; |
| |
| /** |
| * The base directory. |
| * |
| * @parameter expression="${basedir}" |
| * @required |
| */ |
| private File basedir; |
| |
| /** |
| * @parameter default-value="${settings}" |
| * @required |
| * @readonly |
| */ |
| private Settings settings; |
| |
| /** |
| * List of System properties to pass to the JUnit tests. |
| * |
| * @parameter |
| */ |
| private Properties systemProperties; |
| |
| /** |
| * List of provider implementations. |
| * |
| * @parameter |
| */ |
| private Map<String,String> providerImplementations; |
| |
| /** |
| * Should distributed changes be pushed to the central repository? |
| * For many distributed SCMs like Git, a change like a commit |
| * is only stored in your local copy of the repository. Pushing |
| * the change allows your to more easily share it with other users. |
| * |
| * @parameter expression="${pushChanges}" default-value="true" |
| * @since 1.4 |
| */ |
| private boolean pushChanges; |
| |
| /** {@inheritDoc} */ |
| public void execute() |
| throws MojoExecutionException |
| { |
| if ( systemProperties != null ) |
| { |
| // Add all system properties configured by the user |
| Iterator<Object> iter = systemProperties.keySet().iterator(); |
| |
| while ( iter.hasNext() ) |
| { |
| String key = (String) iter.next(); |
| |
| String value = systemProperties.getProperty( key ); |
| |
| System.setProperty( key, value ); |
| } |
| } |
| |
| if ( providerImplementations != null && !providerImplementations.isEmpty() ) |
| { |
| for ( Entry<String,String> entry : providerImplementations.entrySet() ) |
| { |
| String providerType = entry.getKey(); |
| String providerImplementation = entry.getValue(); |
| getLog().info( |
| "Change the default '" + providerType + "' provider implementation to '" |
| + providerImplementation + "'." ); |
| getScmManager().setScmProviderImplementation( providerType, providerImplementation ); |
| } |
| } |
| } |
| |
| protected void setConnectionType( String connectionType ) |
| { |
| this.connectionType = connectionType; |
| } |
| |
| public String getConnectionUrl() |
| { |
| boolean requireDeveloperConnection = !"connection".equals( connectionType.toLowerCase() ); |
| if ( StringUtils.isNotEmpty( connectionUrl ) && !requireDeveloperConnection ) |
| { |
| return connectionUrl; |
| } |
| else if ( StringUtils.isNotEmpty( developerConnectionUrl ) ) |
| { |
| return developerConnectionUrl; |
| } |
| if ( requireDeveloperConnection ) |
| { |
| throw new NullPointerException( "You need to define a developerConnectionUrl parameter" ); |
| } |
| else |
| { |
| throw new NullPointerException( "You need to define a connectionUrl parameter" ); |
| } |
| } |
| |
| public void setConnectionUrl( String connectionUrl ) |
| { |
| this.connectionUrl = connectionUrl; |
| } |
| |
| public File getWorkingDirectory() |
| { |
| if ( workingDirectory == null ) |
| { |
| return basedir; |
| } |
| |
| return workingDirectory; |
| } |
| |
| public void setWorkingDirectory( File workingDirectory ) |
| { |
| this.workingDirectory = workingDirectory; |
| } |
| |
| public ScmManager getScmManager() |
| { |
| return manager; |
| } |
| |
| public ScmFileSet getFileSet() |
| throws IOException |
| { |
| if ( includes != null || excludes != null ) |
| { |
| return new ScmFileSet( getWorkingDirectory(), includes, excludes ); |
| } |
| else |
| { |
| return new ScmFileSet( getWorkingDirectory() ); |
| } |
| } |
| |
| public ScmRepository getScmRepository() |
| throws ScmException |
| { |
| ScmRepository repository; |
| |
| try |
| { |
| repository = getScmManager().makeScmRepository( getConnectionUrl() ); |
| |
| ScmProviderRepository providerRepo = repository.getProviderRepository(); |
| |
| providerRepo.setPushChanges( pushChanges ); |
| |
| if ( !StringUtils.isEmpty( username ) ) |
| { |
| providerRepo.setUser( username ); |
| } |
| |
| if ( !StringUtils.isEmpty( password ) ) |
| { |
| providerRepo.setPassword( password ); |
| } |
| |
| if ( repository.getProviderRepository() instanceof ScmProviderRepositoryWithHost ) |
| { |
| ScmProviderRepositoryWithHost repo = (ScmProviderRepositoryWithHost) repository.getProviderRepository(); |
| |
| loadInfosFromSettings( repo ); |
| |
| if ( !StringUtils.isEmpty( username ) ) |
| { |
| repo.setUser( username ); |
| } |
| |
| if ( !StringUtils.isEmpty( password ) ) |
| { |
| repo.setPassword( password ); |
| } |
| |
| if ( !StringUtils.isEmpty( privateKey ) ) |
| { |
| repo.setPrivateKey( privateKey ); |
| } |
| |
| if ( !StringUtils.isEmpty( passphrase ) ) |
| { |
| repo.setPassphrase( passphrase ); |
| } |
| } |
| |
| if ( !StringUtils.isEmpty( tagBase ) && repository.getProvider().equals( "svn" ) ) |
| { |
| SvnScmProviderRepository svnRepo = (SvnScmProviderRepository) repository.getProviderRepository(); |
| |
| svnRepo.setTagBase( tagBase ); |
| } |
| } |
| catch ( ScmRepositoryException e ) |
| { |
| if ( !e.getValidationMessages().isEmpty() ) |
| { |
| for ( String message : e.getValidationMessages() ) |
| { |
| getLog().error( message ); |
| } |
| } |
| |
| throw new ScmException( "Can't load the scm provider.", e ); |
| } |
| catch ( Exception e ) |
| { |
| throw new ScmException( "Can't load the scm provider.", e ); |
| } |
| |
| return repository; |
| } |
| |
| /** |
| * Load username password from settings if user has not set them in JVM properties |
| * |
| * @param repo not null |
| */ |
| private void loadInfosFromSettings( ScmProviderRepositoryWithHost repo ) |
| { |
| if ( username == null || password == null ) |
| { |
| String host = repo.getHost(); |
| |
| int port = repo.getPort(); |
| |
| if ( port > 0 ) |
| { |
| host += ":" + port; |
| } |
| |
| Server server = this.settings.getServer( host ); |
| |
| if ( server != null ) |
| { |
| if ( username == null ) |
| { |
| username = server.getUsername(); |
| } |
| |
| if ( password == null ) |
| { |
| password = decrypt( server.getPassword(), host ); |
| } |
| |
| if ( privateKey == null ) |
| { |
| privateKey = server.getPrivateKey(); |
| } |
| |
| if ( passphrase == null ) |
| { |
| passphrase = decrypt( server.getPassphrase(), host ); |
| } |
| } |
| } |
| } |
| |
| private String decrypt( String str, String server ) |
| { |
| try |
| { |
| return secDispatcher.decrypt( str ); |
| } |
| catch ( SecDispatcherException e ) |
| { |
| getLog().warn( "Failed to decrypt password/passphrase for server " + server + ", using auth token as is" ); |
| return str; |
| } |
| } |
| |
| public void checkResult( ScmResult result ) |
| throws MojoExecutionException |
| { |
| if ( !result.isSuccess() ) |
| { |
| getLog().error( "Provider message:" ); |
| |
| getLog().error( result.getProviderMessage() == null ? "" : result.getProviderMessage() ); |
| |
| getLog().error( "Command output:" ); |
| |
| getLog().error( result.getCommandOutput() == null ? "" : result.getCommandOutput() ); |
| |
| throw new MojoExecutionException( |
| "Command failed." + StringUtils.defaultString( result.getProviderMessage() ) ); |
| } |
| } |
| |
| public String getIncludes() |
| { |
| return includes; |
| } |
| |
| public void setIncludes( String includes ) |
| { |
| this.includes = includes; |
| } |
| |
| public String getExcludes() |
| { |
| return excludes; |
| } |
| |
| public void setExcludes( String excludes ) |
| { |
| this.excludes = excludes; |
| } |
| |
| public ScmVersion getScmVersion( String versionType, String version ) |
| throws MojoExecutionException |
| { |
| if ( StringUtils.isEmpty( versionType ) && StringUtils.isNotEmpty( version ) ) |
| { |
| throw new MojoExecutionException( "You must specify the version type." ); |
| } |
| |
| if ( StringUtils.isEmpty( version ) ) |
| { |
| return null; |
| } |
| |
| if ( "branch".equals( versionType ) ) |
| { |
| return new ScmBranch( version ); |
| } |
| |
| if ( "tag".equals( versionType ) ) |
| { |
| return new ScmTag( version ); |
| } |
| |
| if ( "revision".equals( versionType ) ) |
| { |
| return new ScmRevision( version ); |
| } |
| |
| throw new MojoExecutionException( "Unknown '" + versionType + "' version type." ); |
| } |
| |
| protected void handleExcludesIncludesAfterCheckoutAndExport( File checkoutDirectory ) |
| throws MojoExecutionException |
| { |
| List<String> includes = new ArrayList<String>(); |
| |
| if ( ! StringUtils.isBlank( this.getIncludes() ) ) |
| { |
| String[] tokens = StringUtils.split( this.getIncludes(), "," ); |
| for ( int i = 0; i < tokens.length; ++i ) |
| { |
| includes.add( tokens[i] ); |
| } |
| } |
| |
| List<String> excludes = new ArrayList<String>(); |
| |
| if ( ! StringUtils.isBlank( this.getExcludes() ) ) |
| { |
| String[] tokens = StringUtils.split( this.getExcludes(), "," ); |
| for ( int i = 0; i < tokens.length; ++i ) |
| { |
| excludes.add( tokens[i] ); |
| } |
| } |
| |
| if ( includes.isEmpty() && excludes.isEmpty() ) |
| { |
| return; |
| } |
| |
| FileSetManager fileSetManager = new FileSetManager(); |
| |
| FileSet fileset = new FileSet(); |
| fileset.setDirectory( checkoutDirectory.getAbsolutePath() ); |
| fileset.setIncludes( excludes );//revert the order to do the delete |
| fileset.setExcludes( includes ); |
| fileset.setUseDefaultExcludes( false ); |
| |
| try |
| { |
| fileSetManager.delete( fileset ); |
| } |
| catch ( IOException e ) |
| { |
| throw new MojoExecutionException( "Error found while cleaning up output directory base on excludes/includes configurations.", e ); |
| } |
| |
| } |
| } |