| /* |
| * 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. |
| */ |
| package org.apache.maven.scm.plugin; |
| |
| 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.Objects; |
| import java.util.Properties; |
| |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.maven.plugin.AbstractMojo; |
| import org.apache.maven.plugin.MojoExecutionException; |
| import org.apache.maven.plugins.annotations.Component; |
| import org.apache.maven.plugins.annotations.Parameter; |
| 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.settings.building.SettingsProblem; |
| import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest; |
| import org.apache.maven.settings.crypto.SettingsDecrypter; |
| import org.apache.maven.settings.crypto.SettingsDecryptionResult; |
| import org.apache.maven.shared.model.fileset.FileSet; |
| import org.apache.maven.shared.model.fileset.util.FileSetManager; |
| |
| /** |
| * @author <a href="evenisse@apache.org">Emmanuel Venisse</a> |
| * @author Olivier Lamy |
| */ |
| public abstract class AbstractScmMojo extends AbstractMojo { |
| |
| protected static final String VERSION_TYPE_BRANCH = "branch"; |
| |
| protected static final String VERSION_TYPE_REVISION = "revision"; |
| |
| protected static final String VERSION_TYPE_TAG = "tag"; |
| |
| protected static final String[] VALID_VERSION_TYPES = {VERSION_TYPE_BRANCH, VERSION_TYPE_REVISION, VERSION_TYPE_TAG |
| }; |
| |
| /** |
| * The SCM connection URL. |
| */ |
| @Parameter(property = "connectionUrl", defaultValue = "${project.scm.connection}") |
| private String connectionUrl; |
| |
| /** |
| * The SCM connection URL for developers. |
| */ |
| @Parameter(property = "developerConnectionUrl", defaultValue = "${project.scm.developerConnection}") |
| private String developerConnectionUrl; |
| |
| /** |
| * The type of connection to use (connection or developerConnection). |
| */ |
| @Parameter(property = "connectionType", defaultValue = "connection") |
| private String connectionType; |
| |
| /** |
| * The working directory. |
| */ |
| @Parameter(property = "workingDirectory") |
| private File workingDirectory; |
| |
| /** |
| * The user name. |
| */ |
| @Parameter(property = "username") |
| private String username; |
| |
| /** |
| * The user password. |
| */ |
| @Parameter(property = "password") |
| private String password; |
| |
| /** |
| * The private key. |
| */ |
| @Parameter(property = "privateKey") |
| private String privateKey; |
| |
| /** |
| * The passphrase. |
| */ |
| @Parameter(property = "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(property = "tagBase") |
| private String tagBase; |
| |
| /** |
| * Comma separated list of includes file pattern. |
| */ |
| @Parameter(property = "includes") |
| private String includes; |
| |
| /** |
| * Comma separated list of excludes file pattern. |
| */ |
| @Parameter(property = "excludes") |
| private String excludes; |
| |
| @Component |
| private ScmManager manager; |
| |
| @Component |
| private SettingsDecrypter settingsDecrypter; |
| |
| /** |
| * The base directory. |
| */ |
| @Parameter(property = "basedir", required = true) |
| private File basedir; |
| |
| @Parameter(defaultValue = "${settings}", readonly = true) |
| 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. |
| * |
| * @since 1.4 |
| */ |
| @Parameter(property = "pushChanges", defaultValue = "true") |
| private boolean pushChanges; |
| |
| /** |
| * A workItem for SCMs like RTC, TFS etc, that may require additional |
| * information to perform a pushChange operation. |
| * |
| * @since 1.9.5 |
| */ |
| @Parameter(property = "workItem") |
| @Deprecated |
| private String workItem; |
| |
| /** {@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 ((connectionUrl != null && !connectionUrl.isEmpty()) && !requireDeveloperConnection) { |
| return connectionUrl; |
| } else if (developerConnectionUrl != null && !developerConnectionUrl.isEmpty()) { |
| 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 File getBasedir() { |
| return this.basedir; |
| } |
| |
| 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 (!(workItem == null || workItem.isEmpty())) { |
| providerRepo.setWorkItem(workItem); |
| } |
| |
| if (!(username == null || username.isEmpty())) { |
| providerRepo.setUser(username); |
| } |
| |
| if (!(password == null || password.isEmpty())) { |
| providerRepo.setPassword(password); |
| } |
| |
| if (repository.getProviderRepository() instanceof ScmProviderRepositoryWithHost) { |
| ScmProviderRepositoryWithHost repo = (ScmProviderRepositoryWithHost) repository.getProviderRepository(); |
| |
| loadInfosFromSettings(repo); |
| |
| if (!(username == null || username.isEmpty())) { |
| repo.setUser(username); |
| } |
| |
| if (!(password == null || password.isEmpty())) { |
| repo.setPassword(password); |
| } |
| |
| if (!(privateKey == null || privateKey.isEmpty())) { |
| repo.setPrivateKey(privateKey); |
| } |
| |
| if (!(passphrase == null || passphrase.isEmpty())) { |
| repo.setPassphrase(passphrase); |
| } |
| } |
| |
| if (!(tagBase == null || tagBase.isEmpty()) |
| && 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) { |
| server = decrypt(server); |
| |
| if (username == null) { |
| username = server.getUsername(); |
| } |
| |
| if (password == null) { |
| password = server.getPassword(); |
| } |
| |
| if (privateKey == null) { |
| privateKey = server.getPrivateKey(); |
| } |
| |
| if (passphrase == null) { |
| passphrase = server.getPassphrase(); |
| } |
| } |
| } |
| } |
| |
| private Server decrypt(Server server) { |
| SettingsDecryptionResult result = settingsDecrypter.decrypt(new DefaultSettingsDecryptionRequest(server)); |
| for (SettingsProblem problem : result.getProblems()) { |
| getLog().error(problem.getMessage(), problem.getException()); |
| } |
| |
| return result.getServer(); |
| } |
| |
| 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: " + Objects.toString(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 ((versionType == null || versionType.isEmpty()) && (version != null && !version.isEmpty())) { |
| throw new MojoExecutionException("You must specify the version type."); |
| } |
| |
| if (version == null || version.isEmpty()) { |
| return null; |
| } |
| |
| if (VERSION_TYPE_BRANCH.equals(versionType)) { |
| return new ScmBranch(version); |
| } |
| |
| if (VERSION_TYPE_TAG.equals(versionType)) { |
| return new ScmTag(version); |
| } |
| |
| if (VERSION_TYPE_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); |
| } |
| } |
| } |